26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
53 #pragma package(smart_init)
72 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
73 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
74 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
75 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
76 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
77 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
88 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
89 AnsiString(TrainModeIn));
136 for(
int x = 0; x < 4; x++)
145 for(
int x = 0; x < 4; x++)
154 for(
int x = 0; x < 4; x++)
159 for(
int x = 0; x < 4; x++)
163 for(
int x = 0; x < 3; x++)
201 for(
int x = 0; x < 4; x++)
262 throw Exception(
"Error in attempting to delete FrontCodePtr");
266 for(
int x = 0; x < 4; x++)
270 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
275 for(
int x = 0; x < 4; x++)
279 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
308 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
374 bool TempDerail =
false;
420 else if((NextElementPosition > -1) && (NextEntryPos > -1))
491 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
501 for(
int x = 0; x < 4; x++)
508 for(
int x = 0; x < 4; x++)
769 int LockedVectorNumber;
899 AnsiString ReasonArray[24] = {
"a driver is awaited",
"a guard is awaited",
"of a medical emergency",
"of a technical problem",
"of a security issue",
900 "of a safety issue",
"of a disturbance",
"a train crew member has been taken ill",
"the driver has been taken ill",
"the guard has been taken ill",
901 "a report has been received concerning safety",
"a shoe has been lost under the train",
"of a reported theft",
902 "of an incident involving an animal",
"some luggage has been lost under the train",
"a minor repair is needed",
"a suspicious object has to be dealt with safely",
903 "a door is stuck open",
"additional stock has to be attached",
"a security alert",
"of a train fault",
"of an operating incident",
"safety checks are required",
904 "of a shortage of on train crew"};
911 if(DwellTime < TDateTime(30.0 / 86400))
913 DwellTime = TDateTime(30.0 / 86400);
915 int randval = random(10000);
920 if(randval < Utilities->MinorDelayCutoff)
927 if(randval < Utilities->ModerateDelayCutoff)
934 if(randval < Utilities->MajorDelayCutoff)
949 if(
NewDelay <
double(DwellTime) * 1440)
955 NewDelay -= double(DwellTime) * 1440;
1016 int randval2 = rand() % 24;
1017 AnsiString Reason = ReasonArray[randval2];
1020 " minutes because " + Reason);
1022 " minutes because " + Reason);
1028 " minutes because of a minor problem");
1030 " minutes because of a minor problem");
1182 if(BufferLocation ==
"")
1187 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1249 int NextElementPosition, NextEntryPos;
1273 NextElementPosition = -1;
1276 if((NextElementPosition > -1) && (NextEntryPos > -1))
1421 AnsiString StationName;
1432 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1442 if((NextElementPosition > -1) && (NextEntryPos > -1))
1590 if(TIFEntryPos == 0)
1627 if(NextElementPosition > -1)
1664 AnsiString Loc =
"";
1665 bool LocNamed =
false;
1694 Loc =
"outside railway";
1726 NextElementPosition = -1;
1737 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1755 if((NextElementPosition > -1) && (NextEntryPos > -1))
1793 FirstPair.second).
GetELink() == TempELink))
1798 SecondPair.second).
GetELink() == TempELink))
1812 FirstPair.second).
GetELink() == TempELink))
1817 SecondPair.second).
GetELink() == TempELink))
1831 FirstPair.second).
GetELink() == TempELink))
1836 SecondPair.second).
GetELink() == TempELink))
1866 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1869 int NewLastElement = 0, NewLastExitPos = 0;
1887 if(NewLastElement == -1)
1893 if(NewLastExitPos == -1)
1897 LastElement = NewLastElement;
1898 LastExitPos = NewLastExitPos;
1901 if(CumDistance < 1200)
1907 int FirstDistance = 0;
1908 if(CumDistance >= 1200)
1910 FirstDistance = 100;
1914 FirstDistance = 1200 - CumDistance;
1916 if(FirstDistance < 100)
1918 FirstDistance = 100;
1944 if(VectorIT->RouteNumber == RouteNumber)
1981 " failed when changing aspect.\nTrains can only pass under signaller control.");
2015 LockedVectorNumber)))
2174 for(
int x = 0; x < 4; x++)
2181 for(
int x = 0; x < 4; x++)
2207 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
2212 if(OtherTrainEntryPos == -1)
2214 throw Exception(
"Error - OtherTrainEntryPos not set");
2233 int OtherTrainID = -1;
2234 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2325 bool StopRequired =
false;
2340 int NextElementEntryPos = -1;
2341 int NextElementExitPos = -1;
2342 bool TrainOnNextElement =
false;
2343 bool StopSignalAtNextElement =
false;
2344 if(ForwardConnection)
2352 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2354 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || TrainAtStopLinkPos3 || TrainAtStopLinkPos4 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2410 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2623 if(Code.Length() != 4)
2627 for(
int x = 1; x < 5; x++)
2634 for(
int x = 0; x < 4; x++)
2797 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2810 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2825 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2834 TRect SourceRect, DestRect;
2836 DestRect.init(0, 0, 8, 8);
2839 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2841 TempGraphic->PixelFormat = pf8bit;
2842 TempGraphic->Width = 16;
2843 TempGraphic->Height = 16;
2849 TempGraphic->Transparent =
true;
2853 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2854 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2860 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2868 else if(TempElement.
SpeedTag == 89)
2872 else if(TempElement.
SpeedTag == 90)
2876 else if(TempElement.
SpeedTag == 91)
2880 else if(TempElement.
SpeedTag == 92)
2884 else if(TempElement.
SpeedTag == 93)
2888 else if(TempElement.
SpeedTag == 94)
2892 else if(TempElement.
SpeedTag == 95)
2896 TempGraphic->Transparent =
true;
2900 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2901 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2903 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2910 for(
int x = 0; x < 40; x++)
2925 TempGraphic->Transparent =
true;
2929 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2930 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2932 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2946 TempGraphic->Transparent =
true;
2950 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2951 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2955 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2958 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2963 TempGraphic->Transparent =
true;
2967 int BDVectorPos = -1;
2976 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2981 TempGraphic->Transparent =
true;
2985 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2986 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2988 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2994 TempGraphic->Transparent =
true;
2998 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2999 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
3001 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3267 throw Exception(
"Error, same train on two different bridge tracks");
3313 AnsiString(EntryPos) +
"," +
HeadCode);
3330 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3349 AnsiString(EntryPos) +
"," +
HeadCode);
3358 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3391 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3392 int LockedVectorNumber;
3405 TRect SourceRect, DestRect;
3406 DestRect.init(0, 0, 8, 8);
3413 int FirstELink, SecondELink = -1;
3416 if(RoutePair2.first > -1)
3425 if(SecondELink == -1)
3427 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3432 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3442 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3443 DestGraphic->PixelFormat = pf8bit;
3444 DestGraphic->Width = 8;
3445 DestGraphic->Height = 8;
3446 DestGraphic->Transparent =
true;
3449 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3458 PrefDirElement, LockedVectorNumber))
3473 if(ElementEntryPos > 1)
3495 AnsiString(EntryPos) +
"," +
HeadCode);
3497 bool WrongRoute =
false;
3523 int LinkNumber = TrackElement.
Link[EntryPos];
3524 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3529 bool LogActionErrorCalled =
false;
3539 LogActionErrorCalled =
true;
3556 else if(LinkNumber == 3)
3564 LogActionErrorCalled =
true;
3581 else if(LinkNumber == 7)
3589 LogActionErrorCalled =
true;
3606 else if(LinkNumber == 9)
3614 LogActionErrorCalled =
true;
3646 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3651 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3661 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3666 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3675 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3696 bool ColourError =
false, ColourError2 =
false;
3701 ColourError2 =
true;
3703 for(
int x = 0; x < 4; x++)
3708 ColourError2 =
true;
3714 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3718 for(
int x = 0; x < 4; x++)
3805 AnsiString(EntryPos) +
"," +
HeadCode);
3806 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3807 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3808 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3809 TrainInFrontInSignallerModeFlag =
false;
3810 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3811 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3812 bool SignallerStopRequired =
false;
3826 if(CurrentTrackVectorPosition > -1)
3830 if((EntryPos == 0) || (EntryPos == 2))
3843 else if(EntryPos == 1)
3867 EntryHalfLength = CurrentElementHalfLength;
3872 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3876 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3924 FrontElementMaxSpeed = LimitingSpeed;
3960 double ExitSpeedAtMaxBraking;
3965 ExitSpeedAtMaxBraking = 0;
3975 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3977 SpeedToUse = ExitSpeedAtMaxBraking;
3981 SpeedToUse = LimitingSpeed;
3996 RedSignalFlag =
false;
3997 BuffersFlag =
false;
3998 StationFlag =
false;
3999 BuffersOrContinuationNowFlag =
false;
4000 ContinuationNextFlag =
false;
4003 CumulativeLength += (2 * CurrentElementHalfLength);
4006 SignallerStopRequired =
true;
4028 bool StopRequired =
false;
4044 StationFlag =
false;
4050 BuffersOrContinuationNowFlag =
true;
4052 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
4056 if((EntryPos == 0) || (EntryPos == 2))
4078 if(NextTrackVectorPosition > -1)
4083 if((NextEntryPos == 0) || (NextEntryPos == 2))
4096 else if(NextEntryPos == 1)
4109 if(NextEntryPos > 1)
4123 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
4135 RedSignalFlag =
true;
4156 TrainInFrontInSignallerModeFlag =
true;
4181 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
4193 double MaxHalfSpeed;
4197 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
4199 MaxHalfSpeed = FrontElementMaxSpeed;
4203 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
4211 bool HalfSpeedLimited =
false;
4215 HalfSpeedLimited =
true;
4245 if(HalfSpeedLimited)
4270 if(SignallerStopRequired)
4286 int TempMaxExitSpeed;
4289 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4291 MaxExitSpeedAtHalfBraking = 0;
4295 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4299 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4301 TempMaxExitSpeed = FrontElementMaxSpeed;
4305 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4317 if(ExitSpeedHalfSquared < 10)
4327 if(ExitSpeedFullSquared < 10)
4399 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4400 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4424 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4425 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4435 if(!BuffersOrContinuationNowFlag)
4437 if(NextSpeedLimit < LimitingSpeed)
4439 LimitingSpeed = NextSpeedLimit;
4443 int TempMaxExitSpeed;
4447 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4449 MaxExitSpeedAtHalfBraking = 0;
4453 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4455 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4457 TempMaxExitSpeed = FrontElementMaxSpeed;
4461 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4472 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4485 if(!BuffersOrContinuationNowFlag)
4487 CurrentTrackVectorPosition = NextTrackVectorPosition;
4488 EntryPos = NextEntryPos;
4489 CurrentElementHalfLength = NextElementHalfLength;
4492 ContinuationNextFlag =
true;
4496 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4516 if(ExitSpeedHalfSquared < 10)
4526 if(ExitSpeedFullSquared < 10)
4589 double DeltaExitTimeToMaxInSecs;
4590 double DistanceToMax;
4599 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4601 DistanceToMax = EntryHalfLength;
4604 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4605 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4622 double DeltaExitTimeToMaxInSecs;
4623 double DistanceToMax;
4632 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4634 DistanceToMax = EntryHalfLength / 2;
4637 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4638 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4649 if(ExitSpeedHalfSquared < 10)
4659 if(ExitSpeedFullSquared < 10)
4678 if((EntryPos == 0) || (EntryPos == 2))
4700 if(NextTrackVectorPosition > -1)
4702 int NextElementLength;
4703 if(NextEntryPos > 1)
4711 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4907 int ElementCount = 0;
4915 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4973 if((EntryPos == 0) || (EntryPos == 2))
4995 CurrentTrackVectorPosition = NextTrackVectorPosition;
4996 EntryPos = NextEntryPos;
4998 if(ElementCount > 1000)
5026 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
5051 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
5052 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
5053 int RouteStartPosition;
5055 int PlatformPosition;
5057 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
5073 if(Distance > (4000 + LeadElementDistance))
5096 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
5099 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
5145 if(!PlatformFoundFlag)
5147 PlatformPosition = CurrentTrackVectorPosition;
5150 PlatformFoundFlag =
true;
5166 if((EntryPos == 0) || (EntryPos == 2))
5210 if(ElementNumber < 2)
5212 SkipRouteCheck =
true;
5216 SkipRouteCheck =
false;
5218 if(ElementNumber == 1)
5220 RouteStartPosition = CurrentTrackVectorPosition;
5230 if(ElementNumber > 1)
5234 RouteOrPartRouteSet =
true;
5238 RouteOrPartRouteSet =
false;
5241 if(!SkipRouteCheck && !RouteOrPartRouteSet)
5248 int ExitLink = CurrentTrackElement.
Link[ExitPos];
5249 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
5261 Distance += CurrentTrackElement.
Length01;
5265 Distance += CurrentTrackElement.
Length23;
5267 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
5268 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
5269 CurrentTrackVectorPosition = NextTrackVectorPosition;
5270 EntryPos = NextEntryPos;
5307 return(RepeatHeadCode);
5329 bool FrontValid =
false, RearValid =
false;
5330 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5334 TrainToBeJoinedBy = NULL;
5348 int TrainToBeJoinedByID = -1;
5369 if((TrainToBeJoinedByID < 0) && RearValid)
5388 if(TrainToBeJoinedByID < 0)
5390 TrainToBeJoinedBy = NULL;
5395 if(!TrainToBeJoinedBy->
Stopped())
5397 TrainToBeJoinedBy = NULL;
5407 void TTrain::LogAction(
int Caller, AnsiString OwnHeadCode, AnsiString OtherHeadCode,
TActionType ActionType, AnsiString LocationName, AnsiString SplitDistribution,
5408 TDateTime TimetableNonRepeatTime,
bool Warning)
5444 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5445 AnsiString BaseLog =
"", WarningBaseLog =
"", ReminderBaseLog =
"", PerfLog =
"", ActionLog =
"";
5446 int IntMinsLate = 0;
5447 bool TTEvent =
false;
5452 ActionLog =
" arrived at ";
5462 ActionLog =
" terminated at ";
5468 ActionLog =
" departed from ";
5471 if(ActionType ==
Pass)
5473 ActionLog =
" passed ";
5478 ActionLog =
" created at ";
5480 if(ActionType ==
Enter)
5482 ActionLog =
" entered railway at ";
5486 ActionLog =
" changed its description to '" +
Description +
"' at ";
5489 if(ActionType ==
Leave)
5491 ActionLog =
" left railway at ";
5496 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from front to ";
5501 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from rear to ";
5506 ActionLog =
" joined by ";
5511 ActionLog =
" changed direction at ";
5516 ActionLog =
" became new service ";
5521 ActionLog =
" taken under signaller control at ";
5525 ActionLog =
" restored to timetable control at ";
5531 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5535 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5539 ActionLog =
" REMOVED FROM RAILWAY at ";
5544 ActionLog =
" received signaller authority to proceed";
5548 ActionLog =
" received signaller authority to step forward";
5552 ActionLog =
" changed direction under signaller control at ";
5556 ActionLog =
" received signaller authority to pass stop signal";
5560 ActionLog =
" received signaller instruction to stop";
5564 ActionLog =
" stopped on signaller instruction ";
5568 ActionLog =
" joined under signaller control by ";
5572 ActionLog =
" suffered an onboard power failure at ";
5576 ActionLog =
" failure repaired at ";
5580 ActionLog =
" left railway under signaller control at ";
5582 if(OtherHeadCode !=
"")
5584 OtherHeadCode +=
" at ";
5616 bool TimePerformance =
true;
5624 TimePerformance =
false;
5628 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5630 if(ActionType ==
Pass)
5644 IntMinsLate = int(ceil(MinsLate));
5648 IntMinsLate = int(floor(MinsLate));
5650 if(IntMinsLate == 0)
5652 PerfLog =
" on time";
5654 else if(IntMinsLate == 1)
5656 PerfLog =
" 1 minute late";
5658 else if(IntMinsLate == -1)
5660 PerfLog =
" 1 minute early";
5662 else if(IntMinsLate > 1)
5664 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
5666 else if(IntMinsLate < -1)
5668 int PosIntMinsLate = -IntMinsLate;
5669 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
5671 if(LocationName.Pos(
'-') > 0)
5673 PerfLog =
"," + PerfLog;
5686 if(ReminderBaseLog !=
"")
5689 ReminderBaseLog =
"";
5693 if((ActionType ==
Arrive) && (IntMinsLate == 0))
5697 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
5702 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
5708 else if((ActionType ==
Pass) && (IntMinsLate == 0))
5712 else if((ActionType ==
Pass) && (IntMinsLate > 0))
5717 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5723 else if((ActionType ==
Leave) && (IntMinsLate == 0))
5727 else if((ActionType ==
Leave) && (IntMinsLate > 0))
5732 else if((ActionType ==
Leave) && (IntMinsLate < 0))
5738 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5742 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5761 AnsiString LocName =
"";
5832 if(LocationName ==
"")
5836 int RearTrainRearPos, RearTrainFrontPos, RearTrainExitPos;
5837 int FrontTrainRearPos, FrontTrainFrontPos;
5840 if(LocationName ==
"")
5842 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5846 bool TemporaryDelay =
false;
5848 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
5872 AnsiString SplittingTrainDescription =
Description;
5879 for(
int x = 0; x < 4; x++)
5899 double NewTrainPowerAtRail;
5905 NewTrainMass =
Mass * double(MassPercent)/100.0;
5907 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
5908 if(NewTrainPowerAtRail == 0)
5910 NewTrainPowerAtRail = 0.08;
5918 NewTrainMass =
Mass;
5946 if(!SplitTrainExplicitDescription)
5991 if(LocationName ==
"")
5995 int RearTrainRearPos, RearTrainFrontPos;
5996 int FrontTrainRearPos, FrontTrainFrontPos, FrontTrainExitPos;
5999 if(LocationName ==
"")
6001 throw Exception(
"Error - LocationName not set in RearTrainSplit");
6005 bool TemporaryDelay =
false;
6007 MidEntryPos, FrontTrainFrontPos, FrontTrainRearPos, RearTrainFrontPos, RearTrainRearPos, TemporaryDelay))
6031 AnsiString SplittingTrainDescription =
Description;
6038 for(
int x = 0; x < 4; x++)
6058 double NewTrainPowerAtRail;
6064 NewTrainMass =
Mass * double(MassPercent)/100.0;
6066 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
6067 if(NewTrainPowerAtRail == 0)
6069 NewTrainPowerAtRail = 0.08;
6077 NewTrainMass =
Mass;
6105 if(!SplitTrainExplicitDescription)
6196 TTrain *TrainToBeJoinedBy;
6229 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6231 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6295 int RouteNumber = -1;
6300 int CorrectRouteID = OR.
RouteID;
6306 bool FirstPass =
true;
6311 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6445 for(
int x = 0; x < IncNum; x++)
6478 else if(Ptr->
Command ==
"jbo")
6483 else if(Ptr->
Command ==
"dsc")
6494 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6500 bool IncludeFER =
false;
6508 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6513 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6524 else if(Ptr->
Command ==
"Fjo")
6530 else if(Ptr->
Command ==
"Frh")
6540 else if(Ptr->
Command ==
"Frh-sh")
6591 else if(Ptr->
Command ==
"jbo")
6596 else if(Ptr->
Command ==
"dsc")
6601 else if(Ptr->
Command ==
"cdt")
6609 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
7031 int RouteNumber = -1;
7036 int CorrectRouteID = OR.
RouteID;
7042 bool FirstPass =
true;
7047 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
7075 ",FloatingLabelNextString" +
"," +
HeadCode);
7076 AnsiString RetStr =
"", LocationName =
"";
7079 if(ActionTime == TDateTime(-1))
7083 if(ActionTime == TDateTime(-1))
7089 if(ActionTime != TDateTime(-1))
7097 throw Exception(
"Error - start entry in FloatingLabelNextString");
7141 else if(Ptr->
Command ==
"Fns")
7147 else if(Ptr->
Command ==
"F-nshs")
7178 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7180 else if(Ptr->
Command ==
"Frh")
7182 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7184 else if(Ptr->
Command ==
"Fer")
7186 AnsiString AllowedExits =
"";
7189 else if(Ptr->
Command ==
"Fjo")
7194 else if(Ptr->
Command ==
"jbo")
7199 else if(Ptr->
Command ==
"fsp")
7204 else if(Ptr->
Command ==
"rsp")
7209 else if(Ptr->
Command ==
"cdt")
7213 else if(Ptr->
Command ==
"dsc")
7222 throw Exception(
"Error - start entry in FloatingLabelNextString where TTClockTime > ActionTime");
7266 else if(Ptr->
Command ==
"Fns")
7272 else if(Ptr->
Command ==
"F-nshs")
7303 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7305 else if(Ptr->
Command ==
"Frh")
7307 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7309 else if(Ptr->
Command ==
"Fer")
7311 AnsiString AllowedExits =
"";
7314 else if(Ptr->
Command ==
"Fjo")
7319 else if(Ptr->
Command ==
"jbo")
7324 else if(Ptr->
Command ==
"fsp")
7329 else if(Ptr->
Command ==
"rsp")
7334 else if(Ptr->
Command ==
"cdt")
7338 else if(Ptr->
Command ==
"dsc")
7347 throw Exception(
"Error - start entry in FloatingLabelNextString in final 'else'");
7391 else if(Ptr->
Command ==
"Fns")
7397 else if(Ptr->
Command ==
"F-nshs")
7428 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7430 else if(Ptr->
Command ==
"Frh")
7432 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7434 else if(Ptr->
Command ==
"Fer")
7436 AnsiString AllowedExits =
"";
7439 else if(Ptr->
Command ==
"Fjo")
7444 else if(Ptr->
Command ==
"jbo")
7449 else if(Ptr->
Command ==
"fsp")
7454 else if(Ptr->
Command ==
"rsp")
7459 else if(Ptr->
Command ==
"cdt")
7463 else if(Ptr->
Command ==
"dsc")
7607 + AnsiString(RptNum) +
",GetNewServiceDepartureInfo," +
HeadCode);
7608 AnsiString DepTime =
"", EventTime =
"";
7609 bool CDTFlag =
false;
7611 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
7612 AnsiString TowardsLocation =
"";
7615 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
7617 TowardsLocation = AVI->LocationName;
7619 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
7628 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
7635 if(AVI->Command ==
"cdt")
7640 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
7655 RetStr +=
"\nNew service splits at approx. " + EventTime;
7659 if(AVI->Command ==
"jbo")
7678 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
7693 RetStr +=
"\nNew service finishes and forms another new service at approx. " + EventTime;
7697 if(AVI->Command ==
"Fjo")
7716 if(AVI->Command ==
"Frh")
7718 RetStr +=
"\nNew service finishes and remains at the location.";
7722 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
7729 if(TowardsLocation !=
"")
7731 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
7735 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
7740 if(TowardsLocation !=
"")
7742 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
7746 RetStr +=
"\nNew service departs at " + DepTime;
7755 if(TowardsLocation !=
"")
7757 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
7761 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
7766 if(TowardsLocation !=
"")
7768 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
7772 RetStr +=
"\nNew service departs at approx. " + DepTime;
7789 if(TowardsLocation !=
"")
7791 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
7795 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
7800 if(TowardsLocation !=
"")
7802 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
7806 RetStr +=
"\nNew service departs at approx. " + DepTime;
7825 ",FloatingTimetableString" +
"," +
HeadCode);
7826 AnsiString RetStr =
"", PartStr =
"";
7828 bool SkipDep =
false, SkipDepActedOn =
false;
7834 throw Exception(
"Error - start entry in FloatingTimetableString");
7837 bool FirstPass =
true;
7844 AnsiString TrainLoc =
"";
7897 AnsiString TrainLoc =
"";
7938 else if(Ptr->
Command ==
"Fns")
7944 else if(Ptr->
Command ==
"F-nshs")
7977 else if(Ptr->
Command ==
"Frh")
7981 else if(Ptr->
Command ==
"Fer")
7983 AnsiString AllowedExits =
"";
7986 else if(Ptr->
Command ==
"Fjo")
7991 else if(Ptr->
Command ==
"jbo")
7996 else if(Ptr->
Command ==
"fsp")
8006 PartStr+=
", split mass%-Power% = 50-50";
8009 else if(Ptr->
Command ==
"rsp")
8019 PartStr+=
", split mass%-Power% = 50-50";
8022 else if(Ptr->
Command ==
"cdt")
8026 else if(Ptr->
Command ==
"dsc")
8032 RetStr = RetStr +
'\n' + PartStr;
8046 SkipDepActedOn =
true;
8057 RetStr =
"Timetable finished";
8061 RetStr =
"No timetable";
8065 return(
"Timetable:\n" + RetStr);
8218 bool ForwardHeadCode;
8222 ForwardHeadCode =
true;
8227 ForwardHeadCode =
false;
8370 if(ColourNumber == 0)
8374 else if(ColourNumber == 1)
8378 else if(ColourNumber == 2)
8382 else if(ColourNumber == 3)
8386 else if(ColourNumber == 4)
8390 else if(ColourNumber == 5)
8394 else if(ColourNumber == 6)
8398 else if(ColourNumber == 7)
8402 else if(ColourNumber == 8)
8406 else if(ColourNumber == 9)
8410 else if(ColourNumber == 10)
8414 else if(ColourNumber == 11)
8418 else if(ColourNumber == 12)
8422 else if(ColourNumber == 13)
8426 else if(ColourNumber == 14)
8438 for(
int x = 0; x < 4; x++)
8445 for(
int x = 0; x < 4; x++)
8530 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
8533 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
8534 bool GiveMessagesFalse =
false;
8535 bool CheckLocationsExistInRailwayTrue =
true;
8542 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
8545 if(Marker[6] ==
'1')
9010 bool HideFlashingTrain =
true;
9013 Graphics::TBitmap *SmallTrainBitmap;
9054 HideFlashingTrain =
false;
9059 HideFlashingTrain =
false;
9064 HideFlashingTrain =
false;
9069 HideFlashingTrain =
false;
9074 HideFlashingTrain =
false;
9078 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
9082 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
9106 for(
int y = 0; y < 3; y++)
9110 bool FoundFlag =
false;
9121 if(IMPair.first != IMPair.second)
9148 if((LocationName ==
"") && (
MidElement > -1))
9152 if((LocationName ==
"") && (
LagElement > -1))
9156 if(LocationName ==
"")
9158 throw Exception(
"Error - Location name not set in TrainAtLocation");
9169 for(
int x = 0; x < 4; x++)
9181 for(
int x = 0; x < 4; x++)
9198 AnsiString(LinkNumber) +
"," +
HeadCode);
9250 int DistanceToRedSignal = 0, DistanceToExit = -1;
9251 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
9255 float MinsEarly = 0;
9256 TDateTime DepartureTime;
9257 TDateTime ArrivalTime;
9285 if(TempTTE < LastTimeToExit)
9320 if(TempTTE < LastTimeToExit)
9343 if(TempTTE < LastTimeToExit)
9373 if(TempTTE < LastTimeToExit)
9396 if(TempTTE < LastTimeToExit)
9439 float CurrentStopTime;
9440 float LaterStopTime;
9441 float RecoverableTime;
9449 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
9456 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
9457 bool DistanceToExitSet = (DistanceToExit > -1);
9458 int GenericDistance = DistanceToRedSignal;
9459 if(DistanceToExitSet)
9461 GenericDistance = DistanceToExit;
9477 float TimeToSubtract, TotalStopTime;
9480 TimeToSubtract = RecoverableTime;
9523 if(CurrentStopTime > 0)
9525 TotalStopTime = CurrentStopTime + LaterStopTime;
9534 else if((MinsEarly > 0) && !
Stopped())
9536 TotalStopTime = LaterStopTime + MinsEarly;
9540 if(LaterStopTime == 0)
9542 TotalStopTime = CurrentStopTime;
9548 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
9551 if(AvTrackSpeed < 30)
9555 int Speed = AvTrackSpeed;
9565 if(DistanceToRedSignalSet)
9567 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9577 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9606 if((NextEntryPos == 0) || (NextEntryPos == 2))
9733 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9775 int IncrementalMinutes = 0;
9776 int IncrementalDigits = 0;
9784 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
9820 if(AVEntry0.
Command ==
"Snt-sh")
9825 int IncrementalMinutes = 0;
9826 int IncrementalDigits = 0;
9834 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
9878 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9958 AnsiString Loc =
"";
9959 bool ElementFound =
false;
9964 ElementFound =
true;
9969 ElementFound =
true;
9974 ElementFound =
true;
10003 else if(AVEntryPtr->
Command ==
"Fer")
10005 bool CorrectExit =
false;
10012 CorrectExit =
true;
10117 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10135 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10150 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10161 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
10162 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
10163 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
10165 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
10166 "," + AnsiString(Mass) +
"," + ModeStr);
10168 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr);
10170 int RearExitPos = -1;
10172 for(
int x = 0; x < 4; x++)
10179 if(RearExitPos == -1)
10181 throw Exception(
"Error, RearExit == -1 in AddTrain");
10183 bool ReportFlag =
true;
10188 ReportFlag =
false;
10200 if(ModeStr ==
"Timetable")
10206 if(MaxRunningSpeed < 10)
10208 MaxRunningSpeed = 10;
10210 if(SignallerSpeed < 10)
10212 SignallerSpeed = 10;
10214 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
10215 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
10222 if(SignallerControl)
10252 if(!SignallerControl)
10267 if(!SignallerControl)
10278 AnsiString Loc =
"";
10295 if(!SignallerControl)
10314 int RouteNumber = -1;
10315 bool SignalsSet =
false;
10322 int RouteStartPosition;
10326 if(FirstPair.first == RouteNumber)
10328 RouteStartPosition = FirstPair.second;
10330 else if(SecondPair.first == RouteNumber)
10332 RouteStartPosition = SecondPair.second;
10336 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
10342 else if(RouteNumber > -1)
10362 int LinkedRouteNumber = -1;
10383 int RouteStartPosition;
10387 if(FirstPair.first == RouteNumber)
10389 RouteStartPosition = FirstPair.second;
10391 else if(SecondPair.first == RouteNumber)
10393 RouteStartPosition = SecondPair.second;
10397 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
10403 else if(RouteNumber > -1)
10423 int LinkedRouteNumber = -1;
10444 AnsiString(TrackVectorNumber));
10447 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10456 throw Exception(
"Error, VecPos not set in EntryPos");
10458 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
10463 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
10468 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
10482 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10490 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
10500 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10521 return(RepeatTime);
10530 AnsiString RetStr =
"", PartStr =
"";
10538 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
10546 if(Ptr->SignallerControl)
10548 RetStr =
"Train under signaller control";
10553 if(Ptr->ArrivalTime == Ptr->DepartureTime)
10564 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
10568 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
10572 else if(Ptr->FormatType ==
PassTime)
10576 else if(Ptr->Command ==
"Fns")
10582 else if(Ptr->Command ==
"F-nshs")
10585 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
10592 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10599 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10602 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
10605 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10612 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10614 PartStr =
"Terminate at " + Ptr->LocationName;
10616 else if(Ptr->Command ==
"Frh")
10618 PartStr =
"Terminate at " + Ptr->LocationName;
10620 else if(Ptr->Command ==
"Fer")
10622 AnsiString AllowedExits;
10626 else if(Ptr->Command ==
"Fjo")
10629 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10631 else if(Ptr->Command ==
"jbo")
10634 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10636 else if(Ptr->Command ==
"fsp")
10641 else if(Ptr->Command ==
"rsp")
10646 else if(Ptr->Command ==
"cdt")
10650 else if(Ptr->Command ==
"dsc")
10656 RetStr = RetStr +
'\n' + PartStr;
10664 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
10675 TTrainDataEntry *LinkedTrainDataPtr,
int IncrementalMinutes,
int IncrementalDigits, AnsiString RetStr)
10678 + AnsiString(RptNum) +
",ControllerGetNewServiceDepartureInfo," + TDEPtr->
HeadCode);
10679 AnsiString DepTime =
"", EventTime =
"";
10680 bool CDTFlag =
false;
10682 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
10683 AnsiString TowardsLocation =
"";
10686 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
10688 TowardsLocation = AVI->LocationName;
10690 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
10699 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
10705 if(AVI->Command ==
"cdt")
10707 CDTFlag = !CDTFlag;
10710 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
10713 RetStr +=
"\nNew service splits at " + EventTime;
10717 if(AVI->Command ==
"jbo")
10720 RetStr +=
"\nNew service joined by " +
GetRepeatHeadCode(70, AVI->OtherHeadCode, RptNum, IncrementalDigits) +
" at " + EventTime;
10724 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
10727 RetStr +=
"\nNew service finishes and forms another new service at " + EventTime;
10731 if(AVI->Command ==
"Fjo")
10734 RetStr +=
"\nNew service finishes and joins " +
TrainController->
GetRepeatHeadCode(71, AVI->OtherHeadCode, RptNum, IncrementalDigits) +
" at " + EventTime;
10738 if(AVI->Command ==
"Frh")
10740 RetStr +=
"\nNew service finishes and remains at location.";
10744 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
10749 if(TowardsLocation !=
"")
10751 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
10755 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
10760 if(TowardsLocation !=
"")
10762 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
10766 RetStr +=
"\nNew service departs at " + DepTime;
10931 ActiveTrackElementNameMapEntry.second = 0;
10937 std::ifstream TTBLFile(FileName, std::ios_base::binary);
10940 if(TTBLFile.is_open())
10942 char *TrainTimetableString =
new char[10000];
10944 bool EndOfFile =
false;
10947 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10949 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10956 delete[] TrainTimetableString;
10960 AnsiString OneLine(TrainTimetableString);
10961 bool FinalCallFalse =
false;
10962 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10966 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10967 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10972 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
10974 delete[] TrainTimetableString;
10978 OneLine = AnsiString(TrainTimetableString);
10984 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10986 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10996 OneLine = AnsiString(TrainTimetableString);
10998 if(OneLine.Length() > 9999)
11000 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
11002 delete[] TrainTimetableString;
11006 bool FinalCallFalse =
false;
11007 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11011 delete[] TrainTimetableString;
11015 if(EndOfFile && (Count < 2))
11018 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
11020 delete[] TrainTimetableString;
11026 delete[] TrainTimetableString;
11031 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
11042 bool CheckLocationsExistInRailway)
11170 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
11180 if(OneLine[1] !=
'*')
11182 int SCPos = OneLine.Pos(
';');
11193 bool AllCommas =
true;
11195 for(
int x = 1; x < OneLine.Length() + 1; x++)
11197 if(OneLine[x] !=
',')
11202 if(AllCommas || (OneLine ==
""))
11217 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
11218 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
11219 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
11220 TDateTime StartTime(0);
11222 bool Warning =
false;
11249 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
11250 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
11251 double MaxBrakeRate = 0;
11252 double PowerAtRail = 0;
11253 int SignallerSpeed = 0;
11254 if(OneLine[1] ==
'*')
11260 int Pos = OneLine.Pos(
',');
11263 int SubStringLength = 20;
11264 if(OneLine.Length() < 20)
11266 SubStringLength = OneLine.Length();
11268 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
11272 TrainInfoStr = OneLine.SubString(1, Pos - 1);
11273 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
11284 TempTrainDataEntry.
HeadCode = HeadCode;
11288 if(Description !=
"")
11293 TempTrainDataEntry.
Mass = Mass;
11301 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
11304 while(NewRemainder[NewRemainder.Length()] ==
',')
11306 if(NewRemainder.Length() > 1)
11308 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
11317 if(NewRemainder ==
"")
11319 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
11324 int CommaCount = 0;
11325 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
11327 if(NewRemainder[x] ==
',')
11332 if(CommaCount == 0)
11334 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
11336 int SubStringLength = 20;
11337 if(OneLine.Length() < 20)
11339 SubStringLength = OneLine.Length();
11342 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
11343 OneLine.SubString(1, SubStringLength) +
"'....");
11348 AnsiString OneEntry =
"";
11353 bool FinishFlag =
false;
11355 for(
int x = 0; x < CommaCount + 1; x++)
11357 if((CommaCount == 0) || (x < CommaCount))
11362 if(CommaCount == 0)
11364 OneEntry = NewRemainder;
11369 Pos = NewRemainder.Pos(
',');
11370 OneEntry = NewRemainder.SubString(1, Pos - 1);
11371 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
11377 RearStartOrRepeatMins = 0;
11378 FrontStartOrRepeatDigits = 0;
11379 NumberOfRepeats = 0;
11380 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11381 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11383 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11394 if(Warning && (Second ==
"Frh"))
11396 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
11400 if(Warning && (Second ==
"Fjo"))
11403 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
11440 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
11444 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
11446 if(NewRemainder[1] !=
'R')
11449 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
11455 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11459 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
11462 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
11468 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
11473 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11478 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
11481 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11497 TDateTime TempTime;
11503 ActionVectorEntry.
Warning = Warning;
11519 ActionVectorEntry.
Command = Second;
11534 else if(FormatType ==
TimeCmd)
11540 ActionVectorEntry.
Command = Second;
11548 ActionVectorEntry.
Command = Second;
11549 ActionVectorEntry.
ExitList = ExitList;
11557 ActionVectorEntry.
Command = Second;
11571 ActionVectorEntry.
Command = Second;
11582 ActionVectorEntry.
Command = Second;
11592 ActionVectorEntry.
Command = Second;
11594 if((Second ==
"fsp") || (Second ==
"rsp"))
11609 ActionVectorEntry.
Command = Second;
11618 ActionVectorEntry.
Command = Second;
11624 ActionVectorEntry.
Command = Second;
11632 ActionVectorEntry.
Command = Second;
11635 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11640 OneEntry = NewRemainder;
11645 RearStartOrRepeatMins = 0;
11646 FrontStartOrRepeatDigits = 0;
11647 NumberOfRepeats = 0;
11648 if((FinishFlag) && (OneEntry[1] !=
'R'))
11651 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
11655 if(OneEntry[1] !=
'R')
11657 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11658 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11660 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'.\nIf the program version is not the latest the "
11661 "timetable may have features that aren't compatible with the version in use.");
11678 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
11685 TDateTime TempTime;
11691 ActionVectorEntry.
Warning = Warning;
11698 ActionVectorEntry.
Command = Second;
11706 ActionVectorEntry.
Command = Second;
11715 ActionVectorEntry.
Command = Second;
11724 ActionVectorEntry.
Command = Second;
11734 ActionVectorEntry.
Command = Second;
11735 ActionVectorEntry.
ExitList = ExitList;
11739 ActionVectorEntry.
Command = Second;
11741 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11746 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
11762 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11781 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
11786 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
11801 if(TimeStr.Length() < 5)
11806 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
11811 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
11816 if(TimeStr[3] !=
':')
11821 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
11826 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
11831 while(TimeStr.Length() > 5)
11833 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
11835 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
11836 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
11838 if((WholeHours + FracHour) >= 95.98334)
11843 Time = TDateTime((WholeHours + FracHour) / 24);
11850 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
11851 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
11860 TDateTime TempTime;
11862 if(OneEntry.Length() > 0)
11864 if(OneEntry[1] ==
'W')
11867 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
11871 if(OneEntry ==
"Frh")
11881 if(OneEntry.Length() < 7)
11886 int Pos = OneEntry.Pos(
';');
11894 First = OneEntry.SubString(1, 5);
11900 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
11903 if((Remainder.Length() >= 3) && (Remainder[1] >=
'0') && (Remainder[1] <=
'9') && (Remainder[2] >=
'0') && (Remainder[2] <=
'9') && (Remainder[3] ==
':'))
11906 if(Remainder.Length() < 7)
11911 Pos = Remainder.Pos(
';');
11918 Second = Remainder.SubString(1, 5);
11924 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11937 Pos = Remainder.Pos(
';');
11940 Second = Remainder;
11941 if(Second ==
"cdt")
11966 if((Pos != 4) && (Pos != 7) && (Pos != 8))
11972 Second = Remainder.SubString(1, Pos - 1);
11974 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11976 Pos = Remainder.Pos(
';');
11983 Third = Remainder.SubString(1, Pos - 1);
11984 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11987 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11990 int SpacePos = Third.Pos(
' ');
11996 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
11997 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
11999 if(CheckLocationsExistInRailway)
12009 if(Second ==
"Snt")
12032 if(Second ==
"Sns-sh")
12051 if(Second ==
"F-nshs")
12065 if(Second ==
"Sns-fsh")
12079 if(Second ==
"Fns-sh")
12099 if(Second ==
"pas")
12114 if(Second ==
"Fer")
12121 if(CheckLocationsExistInRailway)
12132 if(Second ==
"dsc")
12134 if(Third.Length() > 60)
12136 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters in '" + Third +
"'");
12140 for(
int x = 1; x < Third.Length() + 1; x++)
12143 if((Third[x] <
' ') && (Third[x] >= 0))
12145 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + Third +
"'");
12161 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
12162 (Second !=
"Frh-sh"))
12174 if(Second ==
"Frh-sh")
12182 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
12186 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
12190 if((Second ==
"Sfs") || (Second ==
"Sns"))
12195 if((Fourth !=
"") && ((Second ==
"fsp") || (Second ==
"rsp")))
12212 bool ErrorFlag =
false;
12214 if((SplitDistributionString.Length() > 6 ) || (SplitDistributionString.Length() < 3))
12218 int pos = SplitDistributionString.Pos(
'-');
12225 AnsiString MassStr = SplitDistributionString.SubString(1, pos - 1);
12226 AnsiString PowerStr = SplitDistributionString.SubString(pos + 1, SplitDistributionString.Length() - pos);
12229 int x = MassStr.ToInt();
12230 int y = PowerStr.ToInt();
12231 if((x > 99) || (x < 1) || (y > 100) || (y < 0))
12236 catch(
const Exception &e)
12243 TimetableMessage(GiveMessages,
"Error in split distribution " + SplitDistributionString +
", should be 'AA-BB' where AA is the percentage mass (min 1, max 99) and BB the percentage " +
12244 "power for the new split-off train");
12265 if((LocStr.Length() >= 3) && (LocStr[1] >=
'0') && (LocStr[1] <=
'9') && (LocStr[2] >=
'0') && (LocStr[2] <=
'9') && (LocStr[3] ==
':'))
12270 for(
int x = 1; x < LocStr.Length() + 1; x++)
12272 if(((LocStr[x] <
' ') && (LocStr[x] >= 0)) || (LocStr[x] ==
',') || (LocStr[x] ==
';'))
12286 if(CheckLocationsExistInRailway)
12291 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
12292 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
12293 "that includes a continuation will not be valid.");
12311 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
12314 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
12319 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
12321 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
12323 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
12329 for(
int x = 3; x >= 0; x--)
12331 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
12332 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
12334 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
12350 AnsiString CurrentID =
"";
12352 if(IDSet.Length() == 0)
12354 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
12358 for(
int x = 1; x <= IDSet.Length(); x++)
12361 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
12363 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
12385 int Pos = IDSet.Pos(
' ');
12396 CurrentID = IDSet.SubString(1, Pos - 1);
12397 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
12409 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
12416 if(!ExitList.empty())
12418 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
12420 if(*ELIT == VecPos)
12422 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
12429 ExitList.push_back(VecPos);
12439 Pos = IDSet.Pos(
' ');
12446 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
12453 AnsiString Remainder =
"";
12454 int SemiColonCount = 0;
12456 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
12458 if(TrainInfoStr[x] ==
';')
12463 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
12465 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
12466 "'. Should be headcode + optional description for a continuing service;" +
12467 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
12471 if(SemiColonCount == 0)
12473 HeadCode = TrainInfoStr;
12482 if(SemiColonCount == 1)
12484 Pos = TrainInfoStr.Pos(
';');
12485 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12486 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12492 if(Description ==
"")
12494 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12498 if(Description.Length() > 60)
12500 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12504 for(
int x = 1; x < Description.Length() + 1; x++)
12507 if((Description[x] <
' ') && (Description[x] >= 0))
12509 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12518 Pos = TrainInfoStr.Pos(
';');
12519 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12520 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12526 Pos = Remainder.Pos(
';');
12527 Description = Remainder.SubString(1, Pos - 1);
12528 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12529 if(Description ==
"")
12531 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12535 if(Description.Length() > 60)
12537 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12541 for(
int x = 1; x < Description.Length() + 1; x++)
12544 if((Description[x] <
' ') && (Description[x] >= 0))
12546 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12551 Pos = Remainder.Pos(
';');
12552 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
12554 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12555 if(StartSpeedStr ==
"")
12557 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
12561 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
12563 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
12565 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
12570 StartSpeed = StartSpeedStr.ToInt();
12576 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12580 Pos = Remainder.Pos(
';');
12581 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
12583 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12584 if(MaxRunningSpeedStr ==
"")
12586 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
12590 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
12592 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
12594 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
12599 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
12605 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12609 if(MaxRunningSpeed < 10)
12612 MaxRunningSpeed = 10;
12615 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12619 Pos = Remainder.Pos(
';');
12620 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
12622 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12625 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
12629 for(
int x = 1; x < MassStr.Length() + 1; x++)
12631 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
12633 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
12638 Mass = MassStr.ToInt() * 1000;
12644 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
12650 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
12654 Pos = Remainder.Pos(
';');
12655 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
12657 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12658 if(MaxBrakeForceStr ==
"")
12660 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
12664 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
12666 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
12668 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
12673 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
12676 if((MaxBrakeForce / Mass) > 1)
12678 MaxBrakeForce = Mass;
12681 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
12685 if((MaxBrakeForce / Mass) < 0.01)
12687 MaxBrakeForce = Mass * 0.01;
12690 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
12695 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
12697 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
12699 if(SemiColonCount == 6)
12701 GrossPowerStr = Remainder;
12702 SignallerSpeedStr =
"30";
12706 Pos = Remainder.Pos(
';');
12707 GrossPowerStr = Remainder.SubString(1, Pos - 1);
12708 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12711 if(GrossPowerStr ==
"")
12713 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
12717 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
12719 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
12721 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
12727 double GrossPower = GrossPowerStr.ToInt() * 1000;
12734 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
12738 else if(GrossPower == 0)
12743 else if((GrossPower > 0) && (GrossPower < 10000))
12746 GrossPower = 10000;
12748 PowerAtRail = GrossPower * 0.8;
12752 if(SignallerSpeedStr ==
"")
12754 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
12758 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
12760 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
12762 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
12767 SignallerSpeed = SignallerSpeedStr.ToInt();
12773 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12777 if(SignallerSpeed < 10)
12780 SignallerSpeed = 10;
12783 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12801 if(OneEntry.Length() < 7)
12803 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12807 int SemiColonCount = 0;
12809 for(
int x = 1; x < OneEntry.Length() + 1; x++)
12811 if(OneEntry[x] ==
';')
12816 if(SemiColonCount != 3)
12818 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12822 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
12824 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12828 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
12833 Pos = Remainder.Pos(
';');
12834 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
12836 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12837 if(MinutesStr ==
"")
12839 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
12843 if(MinutesStr.Length() > 3)
12846 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
12850 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
12852 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
12854 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
12859 RearStartOrRepeatMins = MinutesStr.ToInt();
12860 if(RearStartOrRepeatMins == 0)
12862 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
12866 Pos = Remainder.Pos(
';');
12867 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
12869 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12870 if(DigitsStr ==
"")
12872 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
12876 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
12878 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
12880 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
12885 if(DigitsStr.Length() > 2)
12887 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
12891 FrontStartOrRepeatDigits = DigitsStr.ToInt();
12905 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
12909 AnsiString NumberStr = Remainder;
12911 if(NumberStr ==
"")
12913 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
12917 if(NumberStr.Length() > 4)
12920 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
12924 for(
int x = 1; x < NumberStr.Length() + 1; x++)
12926 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
12929 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
12934 NumberOfRepeats = NumberStr.ToInt();
12935 if(NumberOfRepeats == 0)
12937 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
13211 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
13232 TwoLocationFlag =
false;
13238 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
13252 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
13268 "Error in timetable - a signaller controlled service can have no more than one item (a repeat) after the start event, see: " +
13280 "Error in timetable - a signaller controlled service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
13306 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
13319 SecondPassMessage(GiveMessages,
"Error in timetable - only 'Frh' or 'Fjo' finish events are permitted immediately after "
13320 "an 'Sns' or 'Sfs' event for: " + TDEntry.
HeadCode +
". The program is unable to determine the "
13321 "location of any other type of finish.");
13327 if((AVEntry0.
Command ==
"Snt-sh") || (AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13333 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event can't immediately follow an 'Snt-sh', 'Sns-sh' or 'Sns-fsh' "
13334 "event for: " + TDEntry.
HeadCode);
13344 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13349 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
13359 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13364 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
13374 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13385 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
13395 SecondPassMessage(GiveMessages,
"Error in timetable - the event immediately before the repeat must be a finish for: " + TDEntry.
HeadCode);
13407 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13414 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
13423 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " + TDEntry.
HeadCode);
13442 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
13444 AnsiString LocationName =
"";
13458 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
13459 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13468 if(AVEntry0.
Command ==
"Snt-sh")
13482 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
13498 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh', 'Snt-fsh' or 'Sns-fsh' followed by an illegal event for: " +
13499 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13511 bool FoundFlag =
false;
13515 if((AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13517 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13529 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sns-sh' or 'Sns-fsh' event for: " + TDEntry.
HeadCode);
13542 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13567 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13589 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13611 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13636 bool LocFoundFlag, FnsFoundFlag;
13640 LocFoundFlag =
false;
13641 FnsFoundFlag =
false;
13642 for(
int y =
TrainDataVector.at(x).ActionVector.size() - 1; y >= 0; y--)
13647 FnsFoundFlag =
true;
13656 LocFoundFlag =
true;
13667 SecondPassMessage(GiveMessages,
"Error in timetable - the program can't determine the location of an 'Fns' finish, it must be preceded "
13668 "by an event at the same location that has an identified location name, normally an arrival, see "
13675 if(FnsFoundFlag && !LocFoundFlag)
13677 SecondPassMessage(GiveMessages,
"Error in timetable - the program can't determine the location of an 'Fns' finish, it must be preceded "
13678 "by an event at the same location that has an identified location name, normally an arrival, see "
13692 if(AVEntry0.
Command ==
"Sns")
13704 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sns' event for: " + TDEntry.
HeadCode);
13712 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode +
13713 ". The event isn't valid for a stationary train.");
13721 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode);
13728 TDateTime SnsEventTime = AVEntry0.
EventTime;
13731 bool BreakFlag =
false;
13734 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13739 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SnsServiceRef)
13761 if(AVEntry0.
Command ==
"Sfs")
13763 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13771 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event must be followed by a departure and arrival before another split, see " +
TrainDataVector.at(x).ServiceReference);
13783 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13788 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
13808 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13815 SecondPassMessage(GiveMessages,
"Error in timetable - an 'fsp' or 'rsp' event must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13830 if(AVEntry0.
Command ==
"Sfs")
13842 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sfs' event for: " + TDEntry.
HeadCode);
13850 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode +
13851 ". The event isn't valid for a stationary train.");
13859 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode);
13866 TDateTime SfsEventTime = AVEntry0.
EventTime;
13868 bool BreakFlag =
false;
13871 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13876 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SfsServiceRef)
13896 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13901 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
13922 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13929 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"' must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13934 else if((AVEntry.
Command ==
"Sns") || (AVEntry.
Command ==
"Sfs"))
13937 "Please make sure that the finish event of the service that links to this event is preceded by an "
13938 "event at the same location that has an identified location name, normally an arrival.");
13943 else if(AVEntry.
Command ==
"Snt-sh")
13946 "Please make sure that the service starts with zero speed and is at a named location.");
13951 else if((AVEntry.
Command ==
"Sns-fsh") || (AVEntry.
Command ==
"Sns-sh"))
13954 "Please make sure that the event is followed (not necessarily immediately) by a departure.");
13961 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13974 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13984 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish event for: " + TDEntry.
HeadCode);
13991 if(AVEntry.
Command ==
"F-nshs")
13996 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
14024 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
14025 ". The event isn't valid for a stationary train.");
14035 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
14043 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
14044 ". The event isn't valid for a stationary train.");
14062 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
14063 ". The event isn't valid for a stationary train.");
14081 SecondPassMessage(GiveMessages,
"Error in timetable - a 'dsc' is followed by an illegal event for: " + TDEntry.
HeadCode +
14082 ". The event isn't valid for a stationary train.");
14092 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
14100 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
14101 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
14119 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
14120 ". The event isn't valid for a moving train.");
14142 bool LastEntryIsAnArrival =
false;
14149 LastEntryIsAnArrival =
false;
14150 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14157 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14159 if(LastEntryIsAnArrival)
14163 LastEntryIsAnArrival =
false;
14169 LastEntryIsAnArrival =
true;
14176 LastEntryIsAnArrival =
true;
14177 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14184 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14186 if(LastEntryIsAnArrival)
14190 LastEntryIsAnArrival =
false;
14196 LastEntryIsAnArrival =
true;
14206 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14214 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
14222 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
14223 ". The event isn't valid for a stationary train.");
14234 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
14242 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
14243 ". The event isn't valid for a moving train.");
14257 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14264 throw Exception(
"Timetable error, TimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14268 throw Exception(
"Timetable error, TimeLoc event has neither arrival nor departure time set for " + TDEntry.
HeadCode);
14275 throw Exception(
"Timetable error, TimeTimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14279 throw Exception(
"Timetable error, TimeTimeLoc event has either arrival or departure time not set for " + TDEntry.
HeadCode);
14288 throw Exception(
"Timetable error, Cmd or PassTime event has EventTime not set for " + TDEntry.
HeadCode);
14292 throw Exception(
"Timetable error, Cmd or PassTime event has either arrival or departure time set for " + TDEntry.
HeadCode);
14299 throw Exception(
"Timetable error, Repeat event has a time set for " + TDEntry.
HeadCode);
14310 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14325 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
14333 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
14348 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14360 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14372 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
14373 ", may be before timetable start time");
14384 AnsiString LastLocationName =
"";
14388 bool LastEntryIsAnArrival =
false;
14393 LastEntryIsAnArrival =
false;
14394 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14395 if(LastLocationName !=
"")
14397 throw Exception(
"Timetable error, moving Snt event has LocationName set for " + TDEntry.
HeadCode);
14399 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
14412 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14424 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14437 TwoLocationFlag =
true;
14442 LastEntryIsAnArrival =
false;
14446 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14449 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14454 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
14457 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
14463 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14469 LastEntryIsAnArrival =
true;
14470 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14471 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14483 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14495 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14508 TwoLocationFlag =
true;
14513 LastEntryIsAnArrival =
false;
14517 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14520 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14528 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
14535 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14543 AnsiString LocationNameToBeChecked =
"";
14548 unsigned int y = 0;
14562 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
14563 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
14581 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
14590 TwoLocationFlag =
true;
14601 if(TwoLocationFlag)
14611 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14616 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat event doesn't have a location name set for " + TDEntry.
HeadCode);
14618 AnsiString LocName =
"";
14624 throw Exception(
"Error, 'Snt' event at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
14631 throw Exception(
"Error, 'Snt' unlocated event has a location name set for " + TDEntry.
HeadCode);
14654 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14679 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14701 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14723 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14742 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14745 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
14760 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14765 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
14769 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
14773 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
14777 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
14816 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14818 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
14824 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
14837 int IncMinutes = 0;
14847 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14853 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
14859 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
14864 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
14870 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
14875 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
14888 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14914 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
14922 if(HeadCode.Length() > 4)
14924 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
14935 int ForwardCount = 0;
14936 int ReverseCount = 0;
14938 if(MainHeadCode == SecondHeadCode)
14940 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
14949 if(TDEntry.
HeadCode == MainHeadCode)
14951 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14966 if(ForwardCount == 0)
14969 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
14971 if(ForwardCount > 2)
14974 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
14975 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
14984 if(TDEntry.
HeadCode == SecondHeadCode)
14986 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15001 if(ReverseCount == 0)
15003 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
15008 if(ReverseCount > 2)
15011 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
15012 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
15017 if(ForwardCount != ReverseCount)
15019 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
15020 " than the other way round");
15051 int ForwardCount = 0;
15052 int ReverseCount = 0;
15053 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
15062 if(TDEntry.
HeadCode == MainHeadCode)
15064 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15067 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15072 ForwardEntryPtr = &AVEntry;
15074 ForwardTDVectorNumber = x;
15077 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
15078 (AVEntry.
Command ==
"Frh-sh")))
15083 ForwardEntryPtr = &AVEntry;
15085 ForwardTDVectorNumber = x;
15091 if(ForwardCount == 0)
15094 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
15096 if(ForwardCount > 1)
15098 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
15108 if(TDEntry.
HeadCode == OtherHeadCode)
15110 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15113 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15119 ReverseEntryPtr = &AVEntry;
15120 ReverseTDVectorNumber = x;
15123 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
15129 ReverseEntryPtr = &AVEntry;
15130 ReverseTDVectorNumber = x;
15137 if(ReverseCount == 0)
15139 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
15144 if(ReverseCount > 1)
15146 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
15153 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
15154 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
15155 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
15156 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
15160 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
15167 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
15172 if(SetDataAndCheckLocations)
15174 if(ForwardEntryPtr->LocationName ==
"")
15176 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15177 ". One or other service does not have a location set");
15184 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15185 ". One or other service does not have a location set");
15190 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
15192 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15193 " is at a different location to the referencing train " + MainHeadCode);
15202 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
15204 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15205 " has a different event time to the referencing train " + MainHeadCode);
15213 if(ForwardShuttleStart && ReverseShuttleFinish)
15218 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
15219 " first repeat restart time not consistent with finish service " + OtherHeadCode);
15225 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
15228 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15230 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
15231 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15237 if(ReverseEntryPtr->
Command ==
"Fjo")
15240 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15242 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
15243 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15249 if(ReverseEntryPtr->
Command ==
"Fns")
15252 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15254 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
15255 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15261 if(ForwardEntryPtr->Command ==
"Sfs")
15263 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
15266 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
15273 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
15275 if(ReverseEntryPtr->
Command !=
"Sfs")
15277 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
15285 if(SetDataAndCheckLocations)
15289 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
15296 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
15302 bool StationLocation =
false;
15305 if(TEIt->LocationName == ForwardEntryPtr->LocationName)
15309 StationLocation =
true;
15313 if(StationLocation)
15317 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
15327 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
15333 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15345 if(ForwardEntryPtr->Command ==
"Sns")
15347 if(ReverseEntryPtr->
Command !=
"Fns")
15349 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
15350 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
15356 if(ForwardEntryPtr->Command ==
"Fns")
15358 if(ReverseEntryPtr->
Command !=
"Sns")
15360 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
15361 " and forms a new service with headcode " + OtherHeadCode);
15368 if(SetDataAndCheckLocations)
15370 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15382 if(ForwardEntryPtr->Command ==
"jbo")
15384 if(ReverseEntryPtr->
Command !=
"Fjo")
15386 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
15387 " and is joined by a train with headcode " + OtherHeadCode);
15393 if(ForwardEntryPtr->Command ==
"Fjo")
15395 if(ReverseEntryPtr->
Command !=
"jbo")
15397 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
15398 " and joins a train with headcode " + OtherHeadCode);
15405 if(SetDataAndCheckLocations)
15407 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15423 if(ForwardShuttleStart)
15426 if(!ReverseShuttleFinish)
15429 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
15430 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
15436 if(ReverseShuttleStart)
15439 if(!ForwardShuttleFinish)
15442 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
15443 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
15450 if(SetDataAndCheckLocations)
15452 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15465 bool MainRepeat =
false, OtherRepeat =
false;
15475 OtherRepeat =
true;
15478 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
15480 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
15481 " and the associated train with headcode " + OtherHeadCode);
15486 if(MainRepeat && OtherRepeat)
15492 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
15493 " and the associated train with headcode " + OtherHeadCode);
15515 while(Input[1] ==
' ')
15517 if(Input.Length() > 1)
15519 Input = Input.SubString(2, Input.Length() - 1);
15533 while(Input[Input.Length()] ==
' ')
15535 if(Input.Length() > 1)
15537 Input = Input.SubString(1, Input.Length() - 1);
15547 AnsiString Output =
"";
15548 bool DelimiterFound =
false;
15550 for(
int x = 1; x < Input.Length() + 1; x++)
15554 if(Input[x] ==
' ')
15559 if((Input[x] !=
',') && (Input[x] !=
';'))
15561 DelimiterFound =
false;
15562 Output = Output + Input[x];
15566 DelimiterFound =
true;
15567 Output = Output + Input[x];
15579 DelimiterFound =
false;
15580 for(
int x = Input.Length(); x > 0; x--)
15584 if(Input[x] ==
' ')
15589 if((Input[x] !=
',') && (Input[x] !=
';'))
15591 DelimiterFound =
false;
15592 Output = AnsiString(Input[x]) + Output;
15596 DelimiterFound =
true;
15597 Output = AnsiString(Input[x]) + Output;
15622 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
15624 throw Exception(
"Error, first event not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
15636 LocationName = LocRear;
15640 LocationName = LocFront;
15642 if(LocationName ==
"")
15663 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
15704 int RearPosition = 0, FrontPosition = 0;
15707 if(RearPosition < 0)
15714 if(FrontPosition < 0)
15726 for(
int x = 0; x < 4; x++)
15728 if(RearTrackElement.
Conn[x] == FrontPosition)
15743 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
15750 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
15756 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
15787 AnsiString(RearExitPos));
15798 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
15800 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
15803 AnsiString RearName, FrontName;
15819 FrontName = FrontTrackElement.
ElementID;
15822 int LockedVectorNumber;
15942 if(((RearTrackElement.
Attribute == 1) && (RearExitPos == 1)) || ((RearTrackElement.
Attribute == 0) && (RearExitPos == 3)))
15947 StopTTClockMessage(157, HeadCode +
" can't be created, points set wrongly at " + RearName);
15955 if(((FrontTrackElement.
Attribute == 1) && (FrontEntryPos == 1)) || ((FrontTrackElement.
Attribute == 0) && (FrontEntryPos == 3)))
15960 StopTTClockMessage(158, HeadCode +
" can't be created, points set wrongly at " + RearName);
15994 "," + AnsiString(IncDigits));
15997 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
16002 return(BaseHeadCode);
16004 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
16005 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
16007 while(NextRepeatDigits >= 100)
16009 NextRepeatDigits -= 100;
16011 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
16013 if(NextRepeatDigitsStr.Length() < 2)
16015 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
16017 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
16020 return(NextRepeatHeadCode);
16028 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
16029 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
16031 return(NextRepeatTime);
16040 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
16041 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16042 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16043 int RepeatSecs = RepeatMinutes * 60;
16045 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
16079 NonRepeatingHeadCode);
16080 int ForwardCount = 0;
16081 int ReverseCount = 0;
16082 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
16092 if(TDEntry.
HeadCode == MainHeadCode)
16094 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16100 ForwardEntryPtr = &AVEntry;
16102 ForwardTDVectorNumber = x;
16107 if(ForwardCount == 0)
16110 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
16112 if(ForwardCount > 1)
16114 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
16124 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
16126 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16133 ReverseEntryPtr = &AVEntry;
16134 ReverseTDVectorNumber = x;
16140 if(ReverseCount == 0)
16142 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
16147 if(ReverseCount > 1)
16149 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
16150 NonRepeatingHeadCode);
16155 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
16157 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
16162 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
16164 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
16169 if(SetDataAndCheckLocations)
16171 if(ForwardEntryPtr->LocationName ==
"")
16173 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16174 ". One or other service does not have a location set");
16181 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16182 ". One or other service does not have a location set");
16187 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
16189 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
16190 " is at a different location to the referencing train " + MainHeadCode);
16196 if(ForwardEntryPtr->Command ==
"F-nshs")
16199 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
16201 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
16202 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
16208 if(ForwardEntryPtr->Command ==
"Fns-sh")
16212 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
16214 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
16215 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
16221 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
16224 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
16226 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
16227 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
16245 if(ForwardEntryPtr->Command ==
"Sns-sh")
16247 if(ReverseEntryPtr->
Command !=
"F-nshs")
16249 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
16250 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
16256 if(ForwardEntryPtr->Command ==
"F-nshs")
16258 if(ReverseEntryPtr->
Command !=
"Sns-sh")
16260 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
16261 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
16268 if(SetDataAndCheckLocations)
16270 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16282 if(ForwardEntryPtr->Command ==
"Sns-fsh")
16284 if(ReverseEntryPtr->
Command !=
"Fns-sh")
16287 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
16288 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
16294 if(ForwardEntryPtr->Command ==
"Fns-sh")
16296 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
16299 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
16300 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
16307 if(SetDataAndCheckLocations)
16309 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
16333 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
16334 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16335 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16336 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
16338 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
16362 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
16365 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
16366 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16368 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16370 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16375 while(LastActionCommand ==
"Fns")
16377 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
16378 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16379 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16382 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
16383 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16390 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
16393 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
16394 ". The linking of two or more shuttles is not permitted.");
16414 ShowMessage(
ServiceReference +
" (not a valid service ref.): " + Message);
16432 ShowMessage(Message);
16441 int Mins = Input, Hrs = 0;
16447 AnsiString AnsiMins = AnsiString(Mins);
16448 if(AnsiMins.Length() == 1)
16450 AnsiMins =
"0" + AnsiMins;
16452 AnsiString AnsiHrs = AnsiString(Hrs);
16453 if(AnsiHrs.Length() == 1)
16455 AnsiHrs =
"0" + AnsiHrs;
16458 return(AnsiHrs +
':' + AnsiMins);
16501 AnsiString(ActionEventType) +
"," + LocationID);
16502 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
16507 Prefix =
" ERROR: ";
16510 Prefix =
" HELD: ";
16511 ErrorLog =
" can't enter railway, train obstructing entry position ";
16512 WarningStr =
" can't enter railway, train obstructing entry position ";
16517 Prefix =
" HELD: ";
16518 ErrorLog =
" can't enter railway, route set against it at entry position ";
16519 WarningStr =
" can't enter railway, route set against it at entry position ";
16524 Prefix =
" HELD: ";
16525 ErrorLog =
" can't be created, train obstructing at ";
16526 WarningStr =
" can't be created, train obstructing at ";
16531 Prefix =
" HELD: ";
16532 ErrorLog =
" can't be created on a locked route at ";
16533 WarningStr =
" can't be created on a locked route at ";
16538 Prefix =
" HELD: ";
16539 ErrorLog =
" can't enter on a locked route at ";
16540 WarningStr =
" can't enter on a locked route at ";
16545 Prefix =
" HELD: ";
16546 ErrorLog =
" can't be created, points set wrongly at ";
16547 WarningStr =
" can't be created, points set wrongly at ";
16552 ErrorLog =
" left railway unexpectedly at ";
16557 ErrorLog =
" left railway at an incorrect exit at ";
16562 ErrorLog =
" failed to split - location too short at ";
16563 WarningStr =
" failed to split, location too short at ";
16568 Prefix =
" HELD: ";
16569 ErrorLog =
" unable to split - other train obstructing at ";
16570 WarningStr =
" unable to split - other train obstructing at ";
16575 ErrorLog =
" stopped at buffers unexpectedly at position ";
16579 ErrorLog =
" failed to stop at ";
16584 ErrorLog =
" failed to split at ";
16589 ErrorLog =
" failed to be joined by other train at ";
16594 ErrorLog =
" failed to change its description at ";
16599 ErrorLog =
" failed to join other train at ";
16604 ErrorLog =
" failed to terminate at ";
16609 ErrorLog =
" failed to form new service at ";
16614 ErrorLog =
" failed to exit railway ";
16619 ErrorLog =
" failed to change direction at ";
16624 ErrorLog =
" failed to pass ";
16629 ErrorLog =
" facing buffers and unable to start at ";
16633 ErrorLog =
" DERAILED at position ";
16634 Prefix =
" DERAILMENT: ";
16639 ErrorLog =
" CRASHED INTO BUFFERS at ";
16640 Prefix =
" CRASH: ";
16645 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
16646 Prefix =
" CRASH: ";
16651 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
16652 Prefix =
" CRASH: ";
16656 else if(ActionEventType ==
FailSPAD)
16658 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
16659 Prefix =
" SPAD: ";
16664 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
16665 Prefix =
" SPAD RISK: ";
16670 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
16674 Prefix =
" WARNING: ";
16675 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
16676 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
16681 Prefix =
" WARNING: ";
16682 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
16683 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
16688 Prefix =
" WARNING: ";
16689 ErrorLog =
" is without power so it can't depart from ";
16690 WarningStr =
" is without power so it can't depart from ";
16695 Prefix =
" WARNING: ";
16696 ErrorLog =
" can't depart because there is a train in front at ";
16697 WarningStr =
" can't depart because there is a train in front at ";
16735 std::ofstream OutFile(
"TrainData.csv");
16739 ShowMessage(
"Output file TrainData.csv failed to open");
16746 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
16751 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
16752 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
16753 "RepeatNumber" <<
'\n' <<
'\n';
16754 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16757 AnsiString TimetableEntryTypeStr;
16763 TimetableEntryTypeStr =
"NoFormat";
16769 TimetableEntryTypeStr =
"TimeLoc";
16775 TimetableEntryTypeStr =
"TimeTimeLoc";
16781 TimetableEntryTypeStr =
"TimeCmd";
16787 TimetableEntryTypeStr =
"StartNew";
16793 TimetableEntryTypeStr =
"TimeCmdHeadCode";
16799 TimetableEntryTypeStr =
"FinRemHere";
16805 TimetableEntryTypeStr =
"FNSShuttle";
16811 TimetableEntryTypeStr =
"SNTShuttle";
16817 TimetableEntryTypeStr =
"SNSShuttle";
16823 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
16829 TimetableEntryTypeStr =
"FSHNewService";
16835 TimetableEntryTypeStr =
"Repeat";
16841 TimetableEntryTypeStr =
"Default";
16852 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
16853 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
16856 AnsiString RunningEntryStr;
16862 RunningEntryStr =
"NotStarted";
16868 RunningEntryStr =
"Running";
16874 RunningEntryStr =
"Exited";
16878 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
16895 ShowMessage(Message);
16896 BaseTime = TDateTime::CurrentDateTime();
16910 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
16923 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16925 for(
int x = 0; x < NumberOfTrains; x++)
16927 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16947 int NumberOfTrains;
16954 for(
int x = 0; x < NumberOfTrains; x++)
16991 for(
int x = 0; x < LockedRouteVectorSize; x++)
16998 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
17009 int LockedRouteVectorSize;
17016 for(
int x = 0; x < LockedRouteVectorSize; x++)
17074 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17082 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
17093 int ContinuationAutoSigVectorSize;
17100 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17170 if(AVFirstEntry.
Command ==
"Snt")
17194 CTEMMP.second = CTEEntry;
17201 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
17209 CTEMMP.second = CTEEntry;
17230 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17247 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
17249 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
17260 AnsiString RetStr =
"", PartStr =
"";
17375 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17379 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
17381 AnsiString ShortTTName =
"";
17383 for(
int x = TTFileName.Length(); x > 0; x--)
17385 if(TTFileName[x] ==
'\\')
17387 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
17392 ShowMessage(
"Creates two timetables named " + ShortTTName +
17393 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
17395 Screen->Cursor = TCursor(-11);
17397 AnsiString FormatNoDPStr =
"#######0";
17398 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
17401 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
17408 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
17410 if(TrainDataEntry.
Mass > 0)
17412 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
17416 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
17420 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
17424 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
17426 FirstHeadCode = TrainDataEntry.
HeadCode;
17427 int IncDigits = 0, IncMinutes = 0;
17429 if(!ActionVector.empty())
17431 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
17433 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
17434 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
17452 for(
unsigned int z = 0; z < ActionVector.size(); z++)
17457 AnsiString PartStr =
"", TimeStr =
"";
17474 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17478 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
17488 PartStr =
"Enters at " + LocName;
17501 PartStr =
"Created at " + LocName;
17515 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17520 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17526 else if(ActionVectorEntry.
Command ==
"Sfs")
17528 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
17532 else if(ActionVectorEntry.
Command ==
"Sns")
17534 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17542 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17548 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17556 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17559 AnsiString FirstHeadCode = TDE->
HeadCode;
17563 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
17575 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17577 OneTTEntry.
Action = PartStr;
17578 OneTTEntry.
Time = TimeStr;
17580 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17585 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
17591 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17596 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17604 else if(ActionVectorEntry.
Command ==
"jbo")
17606 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
17610 else if(ActionVectorEntry.
Command ==
"fsp")
17614 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17618 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17623 else if(ActionVectorEntry.
Command ==
"rsp")
17627 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17631 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17636 else if(ActionVectorEntry.
Command ==
"cdt")
17638 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
17641 else if(ActionVectorEntry.
Command ==
"dsc")
17643 PartStr =
"Changes description at " + ActionVectorEntry.
LocationName;
17649 if(ActionVectorEntry.
Command ==
"Fns")
17651 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17655 else if(ActionVectorEntry.
Command ==
"F-nshs")
17657 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17663 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
17670 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17676 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17683 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
17688 else if(ActionVectorEntry.
Command ==
"Frh")
17690 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
17695 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
17699 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
17709 else if(ActionVectorEntry.
Command ==
"Fer")
17711 AnsiString AllowedExits;
17715 else if(ActionVectorEntry.
Command ==
"Fjo")
17717 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
17726 OneTTEntry.
Action = PartStr;
17727 OneTTEntry.
Time = TimeStr;
17734 AllTTTrains->push_back(OneTTLine);
17738 std::ofstream TTFile(TTFileName.c_str());
17742 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
17743 delete AllTTTrains;
17778 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
17779 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17781 TTFile << AllTTTrains->at(x).Header.c_str();
17784 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17786 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17788 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
17792 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
17795 TTFile <<
'\n' <<
'\n';
17797 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
17799 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
17800 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17802 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17804 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
17808 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
17813 TTFile <<
'\n' <<
'\n';
17818 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17820 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
17822 std::ofstream TTFile2(TTFileName2.c_str());
17826 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
17827 delete AllTTTrains;
17831 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
17832 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
17833 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
17835 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
17840 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
17841 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17843 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17845 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
17847 bool GiveMessagesFalse =
false;
17848 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
17849 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
17850 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
17855 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
17856 TimeString = TimeString.SubString(9, 5);
17857 ActionString +=
" " + OtherHeadCode;
17859 if(TimeString.SubString(1, 7) ==
"End at ")
17862 TimeString = TimeString.SubString(8, 5);
17864 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
17865 AnsiMultiMapEntry.first = TimeString;
17866 AnsiMultiMapEntry.second = OneLine;
17867 TAMM->insert(AnsiMultiMapEntry);
17872 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
17874 TTFile2 << (AMMIT->second).c_str();
17876 delete AllTTTrains;
17885 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
17889 bool AnalysisError =
false;
17890 AnsiString SequenceLog =
"SequenceLog\n";
17933 TTrainDataVector::iterator TDVIt, TDVCopyIt;
17935 int IteratorNumber = 0;
17936 AnsiString AnsiSuffix =
"";
17943 if(TDVCopyIt->HeadCode == TDVIt->HeadCode)
17946 AnsiSuffix = AnsiString(Suffix);
17947 TDVCopyIt->ServiceReference = TDVIt->HeadCode +
"/" + AnsiSuffix;
17948 TDVCopyIt->HeadCode = TDVIt->HeadCode +
"/" + AnsiSuffix;
17954 int Increment = 0, SlashPos;
17956 AnsiString LinkedHeadCode;
17960 for(AVEIt = TDVCopyIt->ActionVector.begin(); AVEIt != TDVCopyIt->ActionVector.end(); AVEIt++)
17962 if(AVEIt->LinkedTrainEntryPtr != NULL)
17971 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
17973 if(LinkedHeadCode[x] ==
'/')
17975 SlashPos = LinkedHeadCode.Length() - x + 1;
17978 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
17979 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
17980 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
17986 AVEIt->OtherHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
17990 AVEIt->OtherHeadCode =
"";
17992 if(AVEIt->NonRepeatingShuttleLinkEntryPtr != NULL)
17994 Increment = AVEIt->NonRepeatingShuttleLinkEntryPtr - &
TrainDataVector.at(0);
17998 LinkedHeadCode = (*AVEIt->NonRepeatingShuttleLinkEntryPtr).
ServiceReference;
18001 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
18003 if(LinkedHeadCode[x] ==
'/')
18005 SlashPos = LinkedHeadCode.Length() - x + 1;
18008 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
18009 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
18010 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
18016 AVEIt->NonRepeatingShuttleLinkHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
18020 AVEIt->NonRepeatingShuttleLinkHeadCode =
"";
18025 SequenceLog +=
"1\n";
18028 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
18034 ServiceCallingLocsList.clear();
18035 if(ActionVector.empty())
18039 if(ActionVector.at(0).SignallerControl)
18043 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18061 int HLoc = TE.
HLoc;
18062 int VLoc = TE.
VLoc;
18063 AnsiString HString;
18064 AnsiString VString;
18067 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18071 HString = AnsiString(HLoc);
18075 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18079 VString = AnsiString(VLoc);
18081 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18104 else if(AVE.
Command ==
"cdt")
18117 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
18126 ServiceCallingLocsList.push_back(LName);
18130 int HLoc = TE.
HLoc;
18131 int VLoc = TE.
VLoc;
18132 AnsiString HString;
18133 AnsiString VString;
18136 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18140 HString = AnsiString(HLoc);
18144 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18148 VString = AnsiString(VLoc);
18150 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18154 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
18158 SequenceLog +=
"2\n";
18187 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
18193 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
18194 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
18195 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
18197 SequenceLog +=
"3\n";
18204 TDateTime LastTDTime;
18205 int IncMinutes = 0;
18207 if(ActionVector.empty())
18211 if(ActionVector.at(0).SignallerControl)
18215 if(AVLast->FormatType ==
Repeat)
18217 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18225 if(AVLast->ArrivalTime != TDateTime(-1))
18227 LastTDTime = AVLast->ArrivalTime;
18229 else if(AVLast->EventTime != TDateTime(-1))
18231 LastTDTime = AVLast->EventTime;
18250 SequenceLog +=
"4\n";
18287 int IncMinutes = 0;
18289 if(ActionVector.empty())
18293 if(ActionVector.at(0).SignallerControl)
18297 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
18299 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18301 for(
int y = 0; y < NumTrains; y++)
18315 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18330 LocServiceTimesVector.push_back(TLSTEntry);
18333 AnsiString IncTime =
"", FoundStopTime =
"";
18334 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18336 if(ActionVector.at(a).FormatType ==
TimeLoc)
18347 if(FoundStopTime ==
"")
18349 throw Exception(
"Failure to determine FoundStopTime for located Snt");
18351 int WhileCount = 0;
18360 if(IncTime >= FoundStopTime)
18364 LocServiceTimesVector.push_back(TLSTEntry);
18365 if(WhileCount > 2000)
18367 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
18380 int HLoc = TE.
HLoc;
18381 int VLoc = TE.
VLoc;
18382 AnsiString HString;
18383 AnsiString VString;
18386 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18390 HString = AnsiString(HLoc);
18394 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18398 VString = AnsiString(VLoc);
18400 TLSTEntry.
Location = HString +
'-' + VString;
18404 LocServiceTimesVector.push_back(TLSTEntry);
18412 LocServiceTimesVector.push_back(TLSTEntry);
18414 AnsiString IncTime =
"", FoundStopTime =
"";
18415 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18417 if(ActionVector.at(a).FormatType ==
TimeLoc)
18428 if(FoundStopTime ==
"")
18430 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18432 int WhileCount = 0;
18441 if(IncTime >= FoundStopTime)
18445 LocServiceTimesVector.push_back(TLSTEntry);
18446 if(WhileCount > 2000)
18448 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18458 bool SkipAddingMinutes =
false;
18461 LocServiceTimesVector.push_back(TLSTEntry);
18463 AnsiString IncTime =
"", FoundStopTime =
"";
18464 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18466 if(ActionVector.at(a).FormatType ==
TimeLoc)
18474 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr != NULL) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr != NULL)))
18478 LocServiceTimesVector.pop_back();
18479 SkipAddingMinutes =
true;
18484 if(FoundStopTime ==
"")
18486 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18488 if(!SkipAddingMinutes)
18490 int WhileCount = 0;
18499 if(IncTime >= FoundStopTime)
18503 LocServiceTimesVector.push_back(TLSTEntry);
18504 if(WhileCount > 2000)
18506 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18515 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
18517 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
18519 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
18520 LocServiceTimesVector.pop_back();
18521 LocServiceTimesVector.push_back(TLSTEntry);
18526 LocServiceTimesVector.push_back(TLSTEntry);
18532 LocServiceTimesVector.push_back(TLSTEntry);
18551 LocServiceTimesVector.push_back(TLSTEntry);
18555 AnsiString TempDepTime = TLSTEntry.
DepTime;
18557 LocServiceTimesVector.push_back(TLSTEntry);
18559 while(TLSTEntry.
AtLocTime < TempDepTime)
18564 TLSTEntry.
DepTime = TempDepTime;
18565 LocServiceTimesVector.push_back(TLSTEntry);
18569 LocServiceTimesVector.push_back(TLSTEntry);
18580 LocServiceTimesVector.push_back(TLSTEntry);
18583 LocServiceTimesVector.push_back(TLSTEntry);
18600 AnsiString HString;
18601 AnsiString VString;
18604 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18608 HString = AnsiString(HLoc);
18612 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18616 VString = AnsiString(VLoc);
18618 TLSTEntry.
Location = HString +
'-' + VString;
18620 LocServiceTimesVector.push_back(TLSTEntry);
18625 AnsiString FrhTime;
18626 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
18630 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
18638 LocServiceTimesVector.push_back(TLSTEntry);
18644 LocServiceTimesVector.push_back(TLSTEntry);
18649 else if(AVE.
Command ==
"Frh-sh")
18651 if(y == NumTrains - 1)
18657 LocServiceTimesVector.push_back(TLSTEntry);
18663 LocServiceTimesVector.push_back(TLSTEntry);
18676 SequenceLog +=
"5\n";
18709 TLocServiceTimesVector::iterator Ptr1, Ptr2;
18712 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18713 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
18715 std::ofstream TTFile3(TTFileName3.c_str());
18719 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
18723 if(LocServiceTimesVector.empty())
18725 ShowMessage(
"No timetabled services found");
18727 DeleteFile(TTFileName3);
18731 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
18732 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
18733 SequenceLog +=
"6\n";
18962 Ptr1 = LocServiceTimesVector.begin();
18964 while(Ptr2 != LocServiceTimesVector.end())
18966 while(Ptr2->Location == Ptr1->Location)
18969 if(Ptr2 == LocServiceTimesVector.end())
18976 if(Ptr2 != LocServiceTimesVector.end())
18984 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
18985 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
18986 MinuteString =
" minutes";
18987 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
18990 MinuteString =
" minute";
18992 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
18993 TTFile3 <<
",Platforms,Trains\n\n";
18995 Ptr1 = LocServiceTimesVector.begin();
18997 while(Ptr2 != LocServiceTimesVector.end())
18999 PreviousService =
"";
19000 NumTrainsAtLoc = 0;
19001 ServiceAndRepeatNumTotal =
"";
19003 NumPlatsAtThisLocCalculated =
false;
19005 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19007 PreviousService =
"";
19008 NumTrainsAtLoc = 0;
19009 ServiceAndRepeatNumTotal =
"";
19011 NumPlatsAtThisLocCalculated =
false;
19015 if(Ptr2 == LocServiceTimesVector.end())
19020 if(Ptr2 == LocServiceTimesVector.end())
19024 while(Ptr2->Location == Ptr1->Location)
19026 PreviousService =
"";
19027 NumTrainsAtLoc = 0;
19028 ServiceAndRepeatNumTotal =
"";
19029 BasicTime = Ptr1->ArrTime;
19030 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19034 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
19036 BasicTime = Ptr2->ArrTime;
19039 if(Ptr2 == LocServiceTimesVector.end())
19043 if(Ptr2->Location != Ptr1->Location)
19048 if(Ptr2 == LocServiceTimesVector.end())
19052 if(Ptr2->Location != Ptr1->Location)
19058 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
19062 if(!NumPlatsAtThisLocCalculated)
19065 NumPlatsAtThisLocCalculated =
true;
19067 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19069 if(ServiceAndRepeatNumTotal ==
"")
19071 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19072 NumTrainsAtLoc = 1;
19076 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19079 PreviousService = Ptr2->ServiceAndRepeatNum;
19080 if(ServiceAndRepeatNumTotal ==
"")
19082 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19083 NumTrainsAtLoc = 1;
19087 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19091 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
19093 int MaxNumberOfSameDirections = 0;
19094 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
19099 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19103 AnsiString Asterisk =
"";
19104 if(MaxNumberOfSameDirections >= NumPlats)
19109 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19110 ArrivalsPrinted =
true;
19111 ServiceAndRepeatNumTotal =
"";
19113 if(Ptr2 == LocServiceTimesVector.end())
19117 if(Ptr2->Location != Ptr1->Location)
19122 if(Ptr2 == LocServiceTimesVector.end())
19128 if(!ArrivalsPrinted)
19130 TTFile3 <<
"Nothing to report for arrivals";
19135 SequenceLog +=
"7\n";
19140 Ptr1 = LocServiceTimesVector.begin();
19142 while(Ptr2 != LocServiceTimesVector.end())
19144 while(Ptr2->Location == Ptr1->Location)
19147 if(Ptr2 == LocServiceTimesVector.end())
19154 if(Ptr2 != LocServiceTimesVector.end())
19161 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
19162 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
19163 MinuteString =
" minutes";
19164 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19167 MinuteString =
" minute";
19169 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
19170 TTFile3 <<
",Platforms,Trains\n\n";
19172 Ptr1 = LocServiceTimesVector.begin();
19174 while(Ptr2 != LocServiceTimesVector.end())
19176 PreviousService =
"";
19177 NumTrainsAtLoc = 0;
19178 ServiceAndRepeatNumTotal =
"";
19180 NumPlatsAtThisLocCalculated =
false;
19182 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19184 PreviousService =
"";
19185 NumTrainsAtLoc = 0;
19186 ServiceAndRepeatNumTotal =
"";
19188 NumPlatsAtThisLocCalculated =
false;
19192 if(Ptr2 == LocServiceTimesVector.end())
19197 if(Ptr2 == LocServiceTimesVector.end())
19201 while(Ptr2->Location == Ptr1->Location)
19203 PreviousService =
"";
19204 NumTrainsAtLoc = 0;
19205 ServiceAndRepeatNumTotal =
"";
19206 BasicTime = Ptr1->DepTime;
19207 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19211 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
19213 BasicTime = Ptr2->DepTime;
19216 if(Ptr2 == LocServiceTimesVector.end())
19220 if(Ptr2->Location != Ptr1->Location)
19225 if(Ptr2 == LocServiceTimesVector.end())
19229 if(Ptr2->Location != Ptr1->Location)
19235 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
19239 if(!NumPlatsAtThisLocCalculated)
19242 NumPlatsAtThisLocCalculated =
true;
19244 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19246 if(ServiceAndRepeatNumTotal ==
"")
19248 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19249 NumTrainsAtLoc = 1;
19253 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19256 PreviousService = Ptr2->ServiceAndRepeatNum;
19257 if(ServiceAndRepeatNumTotal ==
"")
19259 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19260 NumTrainsAtLoc = 1;
19264 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19268 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
19270 int MaxNumberOfSameDirections = 0;
19271 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
19276 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19280 AnsiString Asterisk =
"";
19281 if(MaxNumberOfSameDirections >= NumPlats)
19286 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19287 DeparturesPrinted =
true;
19288 ServiceAndRepeatNumTotal =
"";
19290 if(Ptr2 == LocServiceTimesVector.end())
19294 if(Ptr2->Location != Ptr1->Location)
19299 if(Ptr2 == LocServiceTimesVector.end())
19305 if(!DeparturesPrinted)
19307 TTFile3 <<
"Nothing to report for departures";
19312 SequenceLog +=
"8\n";
19319 Ptr1 = LocServiceTimesVector.begin();
19321 while(Ptr2 != LocServiceTimesVector.end())
19323 while(Ptr2->Location == Ptr1->Location)
19326 if(Ptr2 == LocServiceTimesVector.end())
19333 if(Ptr2 != LocServiceTimesVector.end())
19340 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
19341 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
19342 TTFile3 <<
",Platforms,Trains,\n\n";
19343 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19344 Ptr1 = LocServiceTimesVector.begin();
19346 while(Ptr2 != LocServiceTimesVector.end())
19348 PreviousService =
"";
19349 ServiceAndRepeatNumTotal =
"";
19350 NumTrainsAtLoc = 0;
19352 NumPlatsAtThisLocCalculated =
false;
19355 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19357 PreviousService =
"";
19358 ServiceAndRepeatNumTotal =
"";
19359 NumTrainsAtLoc = 0;
19361 NumPlatsAtThisLocCalculated =
false;
19365 if(Ptr2 == LocServiceTimesVector.end())
19370 if(Ptr2 == LocServiceTimesVector.end())
19374 while(Ptr2->Location == Ptr1->Location)
19376 if(Ptr1->FrhMarker ==
"Frh")
19379 Ptr1->FrhMarker =
"FrhCounted";
19381 PreviousService =
"";
19382 NumTrainsAtLoc = 0;
19383 ServiceAndRepeatNumTotal =
"";
19384 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19388 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
19391 if(Ptr1->FrhMarker ==
"Frh")
19394 Ptr1->FrhMarker =
"FrhCounted";
19397 if(Ptr2 == LocServiceTimesVector.end())
19401 if(Ptr2->Location != Ptr1->Location)
19406 if(Ptr2 == LocServiceTimesVector.end())
19410 if(Ptr2->Location != Ptr1->Location)
19414 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
19416 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
19420 if(!NumPlatsAtThisLocCalculated)
19423 NumPlatsAtThisLocCalculated =
true;
19425 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19427 if(ServiceAndRepeatNumTotal ==
"")
19429 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
19430 NumTrainsAtLoc = 1;
19434 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
19437 PreviousService = Ptr2->ServiceAndRepeatNum;
19438 if(ServiceAndRepeatNumTotal ==
"")
19440 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
19441 NumTrainsAtLoc = 1;
19445 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
19448 if(Ptr1->FrhMarker ==
"Frh")
19451 Ptr1->FrhMarker =
"FrhCounted";
19454 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
19458 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
19460 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
19462 AnsiString Asterisk =
"";
19463 if(NumTrainsAtLoc > NumPlats)
19470 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19472 else if(FrhCount == 1)
19474 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19478 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19480 LastFrhCount = FrhCount;
19481 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
19482 AtLocsPrinted =
true;
19483 ServiceAndRepeatNumTotal =
"";
19486 if(Ptr2 == LocServiceTimesVector.end())
19490 if(Ptr2->Location != Ptr1->Location)
19495 if(Ptr2 == LocServiceTimesVector.end())
19503 TTFile3 <<
"Nothing to report for trains at locations";
19508 SequenceLog +=
"9\n";
19542 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
19547 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
19556 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19558 SingleServiceEntry = TDE;
19560 for(
unsigned int y = 0; y < SSAV.size(); y++)
19562 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
19564 SingleServiceVector.push_back(SingleServiceEntry);
19567 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
19569 PartServiceEntry = TDE;
19571 for(
unsigned int z = 0; z <= y; z++)
19576 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
19577 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
19580 PartServiceVector.push_back(PartServiceEntry);
19581 if(SSAV.at(y).Command ==
"fsp")
19583 SSAV.at(y).Command =
"Front split - original service continues below";
19584 SSAV.at(y).OtherHeadCode =
"";
19586 if(SSAV.at(y).Command ==
"rsp")
19588 SSAV.at(y).Command =
"Rear split - original service continues below";
19589 SSAV.at(y).OtherHeadCode =
"";
19593 else if(SSAV.at(y).Command ==
"Fns")
19595 SSAV.at(y).Command =
"chr-Fns";
19596 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19597 PartServiceVector.push_back(SingleServiceEntry);
19600 else if(SSAV.at(y).Command ==
"Fns-sh")
19602 SSAV.at(y).Command =
"chr-Fns-sh";
19603 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19604 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19605 PartServiceVector.push_back(SingleServiceEntry);
19608 else if(SSAV.at(y).Command ==
"F-nshs")
19610 SSAV.at(y).Command =
"chr-F-nshs";
19611 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19612 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19613 PartServiceVector.push_back(SingleServiceEntry);
19619 SequenceLog +=
"10\n";
19623 AnsiString NextRef;
19624 while(!PartServiceVector.empty())
19626 PartServiceEntry = PartServiceVector.at(0);
19627 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
19629 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
19631 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
19635 bool FinishType =
true, FoundFlag =
false;
19642 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
19646 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19650 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19656 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19657 SingleServiceVector.push_back(PartServiceVector.at(0));
19658 PartServiceVector.erase(PartServiceVector.begin());
19663 NewPartServiceEntry = PartServiceVector.at(0);
19667 PartServiceVector.push_back(NewPartServiceEntry);
19670 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
19675 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
19678 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19680 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
19683 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19685 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19688 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
19691 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19692 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19693 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19694 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19697 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
19701 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19702 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19703 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19711 SequenceLog += +
"11\n";
19712 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
19716 if(!PartServiceVector.empty())
19718 SequenceLog +=
"12\n";
19719 throw Exception(
"PartServiceVector should be empty here - size = " + AnsiString(PartServiceVector.size()));
19721 SequenceLog +=
"13\n";
19768 bool BufferFacingUnReportedFlag =
true;
19769 bool TrainFacingBuffersReported =
false;
19770 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19776 SequenceLog +=
"13a\n";
19777 throw Exception(
"Repeat entry present in SingleServiceVector at position " + AnsiString(x));
19780 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19782 bool BufferFlag =
false;
19783 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
19784 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
19785 AnsiString FrontLocName = AV.at(0).LocationName;
19786 int NextEntryPos, NextExitPos;
19789 if(ThisElement.
Conn[0] == RearTVPos)
19793 else if(ThisElement.
Conn[1] == RearTVPos)
19797 else if(ThisElement.
Conn[2] == RearTVPos)
19801 else if(ThisElement.
Conn[3] == RearTVPos)
19813 if(ThisElement.
Conn[ThisExitPos] == -1)
19815 SequenceLog =
"13b\n";
19816 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
19819 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
19820 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
19822 BufferFlag =
false;
19827 BufferFlag =
false;
19832 BufferFlag =
false;
19840 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
19842 ThisElement = NextElement;
19848 if(NextEntryPos == 0)
19852 else if(NextEntryPos == 1)
19856 else if(NextEntryPos == 2)
19860 else if(NextEntryPos == 3)
19865 ThisElement = NextElement;
19866 ThisExitPos = NextExitPos;
19871 if(BufferFacingUnReportedFlag)
19873 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
19874 BufferFacingUnReportedFlag =
false;
19876 if(AV.at(1).Command !=
"cdt")
19878 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation with no immediate change of direction\n";
19879 TrainFacingBuffersReported =
true;
19884 if(!TrainFacingBuffersReported)
19886 TTFile3 <<
"Nothing to report for train facing directions\n\n";
19892 SequenceLog +=
"13c\n";
19895 AnsiString LocationNameToBeChecked =
"";
19896 bool MissingcdtUnreportedFlag =
true;
19898 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19901 unsigned int y = 0;
19902 int FirstInstance = 9999, SecondInstance = 9999;
19903 bool FullBreak =
false;
19904 MarkerList.clear();
19906 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
19915 LocationNameToBeChecked =
"";
19921 if(LocationNameToBeChecked ==
"")
19928 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
19931 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
19936 (AVEntry.
Command ==
"Frh-sh"))
19951 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
19953 AnsiString LocationName;
19960 int ExitLoc = TDEntry.
ActionVector.at(a).ExitList.front();
19965 LocationName = TDEntry.
ActionVector.at(a).LocationName;
19967 if(LocationName == LocationNameToBeChecked)
19969 SecondInstance = a;
19971 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
19973 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
19975 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
19978 if(MissingcdtUnreportedFlag)
19980 TTFile3 <<
"Possibly missing changes of direction - these will be missing unless the service travels in a loop back to the locations marked:-\n\n";
19982 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
19983 MarkerList.push_back(FirstInstance);
19984 MarkerList.push_back(SecondInstance);
19986 MissingcdtUnreportedFlag =
false;
19997 if(MissingcdtUnreportedFlag)
19999 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
20005 SequenceLog +=
"14\n";
20014 typedef std::list<AnsiString> TLocList;
20015 TLocList BackwardList, ForwardList;
20016 bool IntroLineNeeded =
true;
20017 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
20019 unsigned int cdtPosition = 9999;
20020 AnsiString cdtLocation =
"";
20021 bool FoundSameName =
false;
20022 bool FerEntry =
false;
20023 MarkerList.clear();
20025 for(
unsigned int y = 0; y <= TDEntry.
ActionVector.size(); y++)
20032 BackwardList.clear();
20033 ForwardList.clear();
20034 bool ValidEnd =
false;
20040 (AVEntry.
Command ==
"Frh-sh"))
20045 if(FerEntry || ValidEnd)
20047 if(MarkerList.empty())
20054 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
20056 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
20058 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
20062 if(IntroLineNeeded)
20064 TTFile3 <<
"Questionable change of direction analysis.\n\n";
20065 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above (up to the start or another direction change)\n";
20066 TTFile3 <<
"and below (down to the end or another direction change) but not counting the change of direction location itself.\n\n";
20067 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
20068 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
20069 IntroLineNeeded =
false;
20071 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
20086 for(
int z = y - 1; z >= 0; z--)
20089 if(AVEntry2.
Command ==
"cdt")
20093 AnsiString LocName =
"";
20103 if((LocName !=
"") && (AVEntry2.
LocationName != cdtLocation))
20105 BackwardList.push_back(LocName);
20108 BackwardList.sort();
20109 BackwardList.unique();
20110 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
20119 AnsiString LocName =
"";
20120 if(AVEntry3.
Command ==
"Fer")
20122 int ExitLoc = AVEntry3.
ExitList.front();
20130 if((LocName !=
"") && (AVEntry3.
LocationName != cdtLocation))
20132 ForwardList.push_back(LocName);
20135 ForwardList.sort();
20136 ForwardList.unique();
20137 FoundSameName =
false;
20139 if(!BackwardList.empty() && !ForwardList.empty())
20141 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
20143 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
20147 FoundSameName =
true;
20154 MarkerList.push_back(cdtPosition);
20159 if(IntroLineNeeded)
20161 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
20179 SequenceLog +=
"15\n";
20185 catch(
const Exception &e)
20187 AnsiString TTErrorFileName =
"Analysis Error.txt";
20188 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
20189 std::ofstream TTError(TTErrorFileName.c_str());
20192 ShowMessage(
"Analysis error file failed to open - can't be created");
20196 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
20197 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
20198 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
20201 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
20211 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
20213 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
20215 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
20217 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
20218 AnsiString Marker =
"";
20219 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
20222 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
20224 if(
int(x) == *MLIt)
20254 if(AVE.
Command.SubString(1,3) ==
"chr")
20263 AVE.
Command =
"Change of service to ";
20265 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
20267 AVE.
Command =
"Change to shuttle finishing service";
20269 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
20296 AnsiString ListOfExits =
"";
20305 VecFile << Marker <<
"Frh" <<
'\n';
20320 for(
unsigned int x = 0; x < Vector.size(); x++)
20323 if(Vector.at(x).ServiceReference == HeadCode)
20325 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
20327 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
20330 FinishType =
false;
20335 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
20338 FinishType =
false;
20343 return(Vector.at(x));
20347 return(Vector.at(Vector.size() - 1));
20356 if((Time1 ==
"") || (Time2 ==
""))
20361 int Mins = Time1.SubString(4,2).ToInt();
20362 int Hours = Time1.SubString(1,2).ToInt();
20363 int Time1Mins = (Hours * 60) + Mins;
20364 Mins = Time2.SubString(4,2).ToInt();
20365 Hours = Time2.SubString(1,2).ToInt();
20366 int Time2Mins = (Hours * 60) + Mins;
20367 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
20379 bool &AnalysisError,
int &MaxNumberOfSameDirections)
20386 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
20388 std::list<AnsiString> ServiceList;
20390 bool EvenComma =
false;
20391 for(
int x = 1; x <= Input.Length(); x++)
20393 TempStr1 = Input[x];
20394 if(TempStr1 == AnsiString(
',') && EvenComma)
20400 TempStr2 += Input[x];
20402 if(TempStr1 == AnsiString(
','))
20404 EvenComma = !EvenComma;
20408 while(TempStr2.Length() > 0)
20410 SCPos = TempStr2.Pos(
';');
20413 OneService = TempStr2.SubString(1, SCPos - 1);
20414 ServiceList.push_back(OneService);
20415 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
20419 ServiceList.push_back(TempStr2);
20423 ServiceList.sort();
20424 ServiceList.unique();
20425 NumTrainsAtLoc = ServiceList.size();
20428 int DirectionMarker = 0;
20430 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
20432 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20434 *SLIt = *SLIt +
"&0";
20436 SLIt3 = ServiceList.end();
20438 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
20439 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
20440 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
20442 MaxNumberOfSameDirections = 0;
20443 int SameDirectionCount = 0;
20445 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
20449 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
20455 CommaPos1 = SLIt1->Pos(
',');
20456 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
20458 SpacePos = ServiceRef1.Pos(
' ');
20462 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
20463 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
20464 if(RepeatInfo1[1] ==
'F')
20470 SpacePos = RepeatInfo1.Pos(
' ');
20471 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
20474 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
20476 AmpersandPos = AnsiTime1.Pos(
'&');
20477 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
20482 throw Exception(
"ASCLIt1 Error in " + Input);
20484 ServiceCallingLocsList1 = ASCLIt1->second;
20485 AmpersandPos = SLIt1->Pos(
'&');
20486 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
20487 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
20489 SameDirectionCount = 1;
20490 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
20492 CommaPos2 = SLIt2->Pos(
',');
20493 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
20495 SpacePos = ServiceRef2.Pos(
' ');
20499 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
20500 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
20501 if(RepeatInfo2[1] ==
'F')
20507 SpacePos = RepeatInfo2.Pos(
' ');
20508 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
20511 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
20513 AmpersandPos = AnsiTime2.Pos(
'&');
20514 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
20519 throw Exception(
"ASCLIt2 Error in " + Input);
20521 ServiceCallingLocsList2 = ASCLIt2->second;
20523 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
20525 int AmpersandPos = SLIt2->Pos(
'&');
20526 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
20527 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
20528 SameDirectionCount++;
20531 if(SameDirectionCount > MaxNumberOfSameDirections)
20533 MaxNumberOfSameDirections = SameDirectionCount;
20538 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
20541 AmpersandPos = SLIt3->Pos(
'&');
20542 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
20543 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
20546 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20549 AmpersandPos = SLIt->Pos(
'&');
20550 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
20551 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
20552 DirectionMarker = DirectionMarkerString.ToInt();
20553 AnsiString DirectionSuffix =
"";
20555 if(DirectionMarker < 27)
20557 c = 64 + DirectionMarker;
20558 DirectionSuffix =
"," + AnsiString(c);
20560 else if(DirectionMarker < 53)
20562 c = 65 + DirectionMarker - 27;
20563 DirectionSuffix =
",A" + AnsiString(c);
20567 DirectionSuffix =
",?";
20569 *SLIt = ServiceWithoutMarker + DirectionSuffix;
20572 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20574 Output = Output + *SLIt +
",";
20576 if(Output.Length() > 0)
20578 Output = Output.SubString(1, Output.Length() - 1);
20584 catch(
const Exception &e)
20586 AnalysisError =
true;
20598 AnsiString InternalInput = Input, Output =
"", OneService =
"";
20600 std::list<AnsiString> ServiceList;
20602 while(InternalInput.Length() > 0)
20604 CommaPos = InternalInput.Pos(
',');
20607 OneService = InternalInput.SubString(1, CommaPos - 1);
20608 ServiceList.push_back(OneService);
20609 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
20613 ServiceList.push_back(InternalInput);
20614 InternalInput =
"";
20618 ServiceList.sort();
20619 ServiceList.unique();
20620 NumTrainsAtLoc = ServiceList.size();
20621 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20623 Output = Output + *SLIt +
",";
20625 if(Output.Length() > 0)
20627 Output = Output.SubString(1, Output.Length() - 1);
20640 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
20642 std::list<AnsiString>::iterator LP1, LP2, ListPtr1, ListPtr2, LocPtr1, LocPtr2;
20647 bool LocFound =
false;
20648 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
20650 TDateTime FirstServiceTime;
20653 int Ref1Target = 0, Ref1Count = 0;
20654 int Ref2Target = 0, Ref2Count = 0;
20672 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
20675 if((*ListPtr1) == Location)
20677 LocPtr1 = ListPtr1;
20680 if(ListPtr1->SubString(1, 3) ==
"%%%")
20682 AnsiString CDTTime = ListPtr1->SubString(4, 5);
20687 FirstServiceTime = TDateTime(-1);
20688 bool BreakFlag =
false;
20691 if(TDVIt->ServiceReference == Ref1)
20693 if(Ref1Target > Ref1Count)
20698 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20699 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20703 FirstServiceTime = AVIt->EventTime;
20709 FirstServiceTime = AVIt->ArrivalTime;
20715 FirstServiceTime = AVIt->DepartureTime;
20726 if(IncMinutes == -1)
20728 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20730 if(FirstServiceTime == TDateTime(-1))
20732 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20736 if(!Arrival && (Time1 == CDTTime))
20741 if(Arrival && (Time1 == CDTTime))
20745 if(Time1 > CDTTime)
20750 if(Time1 < CDTTime)
20763 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
20765 if((*ListPtr2) == Location)
20767 LocPtr2 = ListPtr2;
20770 if(ListPtr2->SubString(1, 3) ==
"%%%")
20772 AnsiString CDTTime = ListPtr2->SubString(4, 5);
20777 FirstServiceTime = TDateTime(-1);
20778 bool BreakFlag =
false;
20781 if(TDVIt->ServiceReference == Ref2)
20783 if(Ref2Target > Ref2Count)
20788 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20789 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20793 FirstServiceTime = AVIt->EventTime;
20799 FirstServiceTime = AVIt->ArrivalTime;
20805 FirstServiceTime = AVIt->DepartureTime;
20816 if(IncMinutes == -1)
20818 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20820 if(FirstServiceTime == TDateTime(-1))
20822 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20826 if(!Arrival && (Time2 == CDTTime))
20831 if(Arrival && (Time2 == CDTTime))
20835 if(Time2 > CDTTime)
20840 if(Time2 < CDTTime)
20855 LP1 = List1.begin();
20857 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
20859 if(ListPtr1 == List1.begin())
20863 if(ListPtr1->SubString(1, 3) ==
"%%%")
20870 LP2 = List2.begin();
20872 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
20874 if(ListPtr2 == List2.begin())
20878 if(ListPtr2->SubString(1, 3) ==
"%%%")
20888 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20890 if(ListPtr1 == LocPtr1)
20894 if(ListPtr1->SubString(1, 3) ==
"%%%")
20898 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20900 if(ListPtr2 == LocPtr2)
20904 if(ListPtr2->SubString(1, 3) ==
"%%%")
20908 if((*ListPtr1) == (*ListPtr2))
20925 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20927 if(ListPtr1 == List1.end())
20931 if(ListPtr1->SubString(1, 3) ==
"%%%")
20935 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20937 if(ListPtr2 == List2.end())
20941 if(ListPtr2->SubString(1, 3) ==
"%%%")
20945 if((*ListPtr1) == (*ListPtr2))
20962 if(ExitList.empty())
20968 AnsiString ExitLocList =
"";
20971 unsigned int Counter = 0;
20972 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
20976 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
20978 ExitLocList +=
"\n";
20981 if(StartName ==
"")
20983 if(ExitList.size() == 1)
20987 return(
" at " + ID);
20992 if(ExitList.size() < 4)
20994 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
20999 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21004 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
21009 if(ExitList.size() < 4)
21011 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21016 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21022 if(ExitList.size() < 4)
21024 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21025 return(
" at " + StartName);
21029 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21030 return(
" at " + StartName);
21070 AnsiString FormatStr =
"####0.0";
21071 AnsiString AvLateArrMins =
"";
21072 AnsiString AvEarlyArrMins =
"";
21073 AnsiString AvLatePassMins =
"";
21074 AnsiString AvEarlyPassMins =
"";
21075 AnsiString AvLateDepMins =
"";
21076 AnsiString AvLateExitMins =
"";
21077 AnsiString AvEarlyExitMins =
"";
21080 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21113 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
21114 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
21126 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21130 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21138 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21142 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21150 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
21158 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21162 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21166 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
21170 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21174 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21178 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
21183 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
21187 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
21191 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21195 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21199 PerfFile <<
LateExits <<
" late exits" <<
'\n';
21203 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21207 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21211 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
21216 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
21220 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
21224 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21228 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21232 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
21234 TDateTime TempExcessLCDownTime;
21248 if(TempExcessLCDownTime > TDateTime(0))
21254 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
21258 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
21270 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
21274 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
21310 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
21314 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
21320 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
21324 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
21327 AnsiString AvLateMinsLocsNotReached =
"";
21333 if(LocsNotReached > 0)
21336 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
21340 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
21344 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
21356 PerfFile <<
Derailments <<
" derailments" <<
'\n';
21360 PerfFile <<
Derailments <<
" derailment" <<
'\n';
21370 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
21372 bool DerailSPADFlag =
false, CrashFlag =
false;
21374 int OverallScorePercent = 100;
21375 int TotArrDepExit = 0;
21376 double TotLateMinsFactor = 1;
21377 double MissedStopAndSPADRiskFactor = 1;
21378 double NetNegFactor = 1;
21388 OverallScorePercent = 5;
21389 DerailSPADFlag =
true;
21393 OverallScorePercent = 0;
21396 if(OverallScorePercent == 100)
21401 LatenessPenalty = 0;
21407 if(TotArrDepExit > 0)
21416 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
21418 OverallScorePercent = 100 * NetNegFactor;
21421 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
21424 AnsiString OneFailureString =
", though the failure would account for some poor performance";
21425 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
21426 AnsiString AddedString =
"";
21429 AddedString = OneFailureString;
21433 AddedString = TwoOrMoreFailureString;
21435 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
21436 AnsiString Rating =
"";
21437 if(OverallScorePercent == 100)
21439 Rating =
"Perfect!";
21441 else if(OverallScorePercent >= 95)
21443 Rating =
"Excellent";
21445 else if(OverallScorePercent >= 90)
21447 Rating =
"Very good";
21449 else if(OverallScorePercent >= 80)
21453 else if(OverallScorePercent >= 70)
21457 else if(OverallScorePercent >= 60)
21459 Rating =
"Unacceptable" + AddedString;
21461 else if(OverallScorePercent >= 50)
21463 Rating =
"Poor" + AddedString;
21465 else if(OverallScorePercent >= 40)
21467 Rating =
"Bad" + AddedString;
21469 else if(OverallScorePercent >= 30)
21471 Rating =
"Very bad" + AddedString;
21473 else if(OverallScorePercent >= 20)
21475 Rating =
"Terrible" + AddedString;
21477 else if(OverallScorePercent >= 10)
21479 Rating =
"Appalling" + AddedString;
21481 else if(OverallScorePercent >= 5)
21485 Rating =
"Disastrous - potential loss of life";
21490 Rating =
"Dire" + AddedString;
21493 else if(OverallScorePercent < 5)
21497 Rating =
"Catastrophic - loss of life";
21501 Rating =
"Abysmal";
21504 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
21508 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
21510 PerfFile <<
'\n' <<
"***************************************";
21520 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21570 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21605 int IncrementalMinutes = 0;
21619 bool TrainOperatingFlag =
false;
21624 TrainOperatingFlag =
true;
21628 if(TrainOperatingFlag)
21636 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
21683 AnsiString HeadCode;
21687 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21691 HCandTrainPosParam.first = HeadCode;
21692 HCandTrainPosParam.second = TrainID;
21694 if((TimeToAct >= 0) && (TimeToAct < 59.9))
21697 OpTimeToActMultiMapEntry.first = TimeToAct;
21698 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21727 float TimeToAct = 0;
21728 int DistanceToRedSignal = 0;
21731 ContinuationEntryVecPosVector.clear();
21732 bool LaterTrain =
false;
21736 LaterTrain =
false;
21737 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
21748 if(!ContinuationEntryVecPosVector.empty())
21750 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
21752 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
21766 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
21767 AnsiString HeadCode = CTEIt->second.HeadCode;
21768 float CurrentStopTime;
21769 float LaterStopTime;
21770 float RecoverableTime;
21773 int DistanceToExit;
21775 bool SigControlAndCanPassRedSignal =
false;
21783 if(CTEIt->second.TrainDataEntryPtr->ActionVector.size() == 1)
21789 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(AtValue),
21790 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
21793 if(AvTrackSpeed < 30)
21797 if(DistanceToRedSignal == -1)
21803 int Speed = AvTrackSpeed;
21804 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
21805 if(AvTrackSpeed > MaxSpeed)
21809 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
21812 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
21815 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
21820 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
21821 TimeToAct += MinsBefEnter;
21824 HCandTrainPosParam.first = HeadCode;
21825 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
21828 if(TimeToAct < 59.9)
21830 OpTimeToActMultiMapEntry.first = TimeToAct;
21831 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21856 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21866 TimeToExitMultiMapEntry.first = ExitPair;
21867 TimeToExitMultiMapEntry.second = ExitInfo;
21877 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
21878 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
21887 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
21888 int DistanceToRedSignal = 0;
21889 DistanceToExit = -1;
21890 ExitPair.first = -1;
21891 ExitPair.second = -1;
21892 int CumTrackSpeed = 0;
21894 int TrackSpeedCount = 0;
21895 float KmPerLocationStop;
21896 float MaxAllowableSpeed;
21906 int CurrentElement = TrackVectorPosition;
21907 int CurrentEntryPos = TrackVectorPositionEntryPos;
21912 CurrentStopTime = 0;
21914 RecoverableTime = 0;
21915 if(CurrentElement == -1)
21920 int CurrentExitPos;
21925 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
21929 CurrentExitPos = 1;
21933 CurrentExitPos = 3;
21938 CurrentExitPos = 0;
21977 TimeToDepart+= 0.5;
21979 if(TimeToDepart < 0.5)
21981 TimeToDepart = 0.5;
21984 CurrentStopTime = float(TimeToDepart);
21992 CurrentStopTime = float(TimeToDepart);
22003 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22014 else if(SigControlAndCanPassRedSignal)
22019 if((NextEntryPos == 0) || (NextEntryPos == 2))
22040 CurrentElement = NextElement;
22041 CurrentEntryPos = NextEntryPos;
22042 CurrentExitPos = NextExitPos;
22054 int LaterStopNumber = 0;
22058 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
22067 if(CurrentEntryPos > 1)
22082 DistanceToExit = DistanceToRedSignal;
22087 if(TrackSpeedCount > 0)
22089 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22093 if(CurrentEntryPos > 1)
22104 if(LaterStopNumber > 0)
22106 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22107 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22113 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22117 if(AvTrackSpeed > MaxAllowableSpeed)
22119 AvTrackSpeed = MaxAllowableSpeed;
22131 bool StopRequired =
false;
22150 int TrainOnElement;
22157 if(CurrentEntryPos > 1)
22166 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
22175 double StopTimeDouble;
22188 if(StopTimeDouble < 0.5)
22190 StopTimeDouble = 0.5;
22194 LaterStopTime += float(StopTimeDouble);
22195 RecoverableTime += StopTimeDouble - 0.5;
22196 if((LaterStopNumber == 1) && (TrainID > -1))
22204 if((AVPtr + 1)->FormatType ==
TimeLoc)
22208 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
22219 if(StopTimeDouble < 0.5)
22221 StopTimeDouble = 0.5;
22224 LaterStopTime += float(StopTimeDouble);
22225 RecoverableTime += StopTimeDouble - 0.5;
22226 if((LaterStopNumber == 1) && (TrainID > -1))
22236 StopTimeDouble = double((AVPtr + 2)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
22247 if(StopTimeDouble < 0.5)
22249 StopTimeDouble = 0.5;
22252 LaterStopTime += float(StopTimeDouble);
22253 RecoverableTime += StopTimeDouble - 0.5;
22254 if((LaterStopNumber == 1) && (TrainID > -1))
22271 if(NextElement == -1)
22280 if((NextEntryPos == 0) || (NextEntryPos == 2))
22301 CurrentElement = NextElement;
22302 CurrentEntryPos = NextEntryPos;
22303 CurrentExitPos = NextExitPos;
22308 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22321 if(TrackSpeedCount > 0)
22323 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22327 if(CurrentEntryPos > 1)
22338 if(LaterStopNumber > 0)
22340 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22341 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22347 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22351 if(AvTrackSpeed > MaxAllowableSpeed)
22353 AvTrackSpeed = MaxAllowableSpeed;
22356 return(DistanceToRedSignal);